package org.etk.reflect.core; import java.util.ArrayList; import java.util.List; import org.etk.reflect.api.ClassTypeInfo; import org.etk.reflect.api.GenericDeclarationInfo; import org.etk.reflect.api.MethodInfo; import org.etk.reflect.api.TypeInfo; import org.etk.reflect.api.TypeVariableInfo; import org.etk.reflect.api.metadata.GenericDeclarationKind; class TypeVariableInfoImpl<T, M, A, P, F> extends AbstractTypeInfo<T, M, A, P, F> implements TypeVariableInfo { private final T type; private final String name; private GenericDeclarationInfo genericDeclaration; private List<TypeInfo> bounds; public TypeVariableInfoImpl(TypeResolverImpl<T, M, A, P, F> domain, T type) { super(domain); this.name = domain.typeMetadata.getName(type); this.type = type; this.genericDeclaration = null; this.bounds = null; } public boolean isReified() { return false; } public String getName() { List<TypeInfo> bounds = getBounds(); if (bounds.isEmpty()) { return Object.class.getName(); } else { return bounds.get(0).getName(); } } public T unwrap() { return type; } public List<TypeInfo> getBounds() { if (bounds == null) { ArrayList<TypeInfo> bounds = new ArrayList<TypeInfo>(); for (T b : domain.typeMetadata.getBounds(type)) { AbstractTypeInfo<T, M, A, P, F> bound = domain.getType(b); bounds.add(bound); } this.bounds = bounds; } return bounds; } public GenericDeclarationInfo getGenericDeclaration() { if (genericDeclaration == null) { GenericDeclarationKind kind = domain.typeMetadata.getGenericDeclarationKind(type); switch (kind) { case TYPE: T gd = domain.typeMetadata.getGenericDeclaration(type); genericDeclaration = (ClassTypeInfo)domain.resolve(gd); break; case METHOD: M mgd = domain.methodMetadata.getGenericDeclaration(type); T omgd = domain.methodMetadata.getOwner(mgd); ClassTypeInfo tmp = (ClassTypeInfo)domain.resolve(omgd); for (MethodInfo mi : tmp.getDeclaredMethods()) { if (mi.unwrap().equals(mgd)) { genericDeclaration = mi; } } if (genericDeclaration == null) { throw new AssertionError("Need to handle that case which could happen due to covariant return types..."); } break; default: throw new UnsupportedOperationException(); } } return genericDeclaration; } public String getVariableName() { return name; } public int hashCode() { return name.hashCode() ^ getGenericDeclaration().hashCode(); } public boolean equals(Object obj) { if (obj == this) { return true; } if (obj instanceof TypeVariableInfo) { TypeVariableInfo that = (TypeVariableInfo)obj; GenericDeclarationInfo generidDeclaration = getGenericDeclaration(); GenericDeclarationInfo thatGenericDeclaration = that.getGenericDeclaration(); String thatName = that.getVariableName(); return name.equals(thatName) && generidDeclaration.equals(thatGenericDeclaration); } return false; } @Override public String toString() { return "TypeVariableInfo[name=" + name + "]"; } }