package bluej.debugger.gentype;
import java.util.*;
| Represent a (possibly generic) type. This can include wildcard types,
| type parameters, etc; ie. anything that JDK 1.5 "Type" can represent.
|*
* Objects of this type are immutable.
*
* @author Davin McCall
*/
public class GenTypeClass extends GenTypeSolid{
// ---------- Instance fields -----------
/** List of type parameters; null if none (there may be an outer class with parameters)
protected List<? extends GenTypeParameter> params = null;
protected Reflective reflective = null;
| Outer class, *iff* an outer class has type parameters; otherwise null
|
protected GenTypeClass outer = null;
| Constructor for a non-generic class type.
|
| @param r The Reflective representing the class.
|
public GenTypeClass(Reflective r)
{
reflective = r;
}
| New GenTypeClass from a reflective and an ordered list of type parameters
|
| @param r The Reflective representing the class.
| @param params A list of GenTypeParameterizables giving the type
| parameters in declaration order
|
public GenTypeClass(Reflective r, List<GenTypeParameter> params)
{
this(r, params, null);
}
| New GenTypeClass from a reflective and an ordered list of type
| parameters, representing an inner class of a specified class.
| This should only be used if the outer class is generic AND this inner
| class is a non-static inner class.<p>
|
| <i>outer</i> may be null, to specify no outer class. In this case this
| constructor is equivalent to GenTypeClass(r, params).
|
| @param r The Reflective representing the class.
| @param params A list of GenTypeParameter giving the type
| parameters in declaration order
|
public GenTypeClass(Reflective r, List<? extends GenTypeParameter> params, GenTypeClass outer)
{
reflective = r;
if (params != null && ! params.isEmpty()) {
this.params = params;
}
this.outer = outer;
}
| New GenTypeClass from a reflective and map of type parameter names to
| types. For type parameters not in the map, the base type is used (as
| a wilcard with "extends" clause). If the map is null however, the type
|* is treated as a raw type.
*
* @param r The Reflective representing the class.
* @param mparams A map of String -> GenTypeParameter giving the
| type parameters. The map may be modified (if it is not
| empty) by this constructor.
|
public GenTypeClass(Reflective r, Map<String,GenTypeParameter> mparams)
{
reflective = r;
if (mparams == null) {
return;
}
List<GenTypeParameter> params = new ArrayList<GenTypeParameter>();
Iterator<GenTypeDeclTpar> declParmsI = r.getTypeParams().iterator();
while ( declParmsI.hasNext() ) {
GenTypeDeclTpar next = declParmsI.next();
String nextName = next.getTparName();
if (mparams.get(nextName) == null)
params.add(new GenTypeExtends(next.getBound()));
else {
params.add((GenTypeParameter) mparams.get(nextName));
mparams.remove(nextName);
}
}
if (params.isEmpty()) {
params = null;
}
this.params = params;
if (! mparams.isEmpty() && ! r.isStatic()) {
Reflective outerReflective = r.getOuterClass();
if (outerReflective != null) {
outer = new GenTypeClass(outerReflective, mparams);
}
}
}
public GenTypeClass asClass()
{
return this;
}
public GenTypeClass getErasedType()
{
return new GenTypeClass(reflective);
}
| Get the name of the type as known to the classloader. The name returned is
| encoded so that it can be passed to a ClassLoader's "loadClass" method (dots
|* between outer and inner class names are changed to '$', and arrays are
* encoded).
*/
public String classloaderName()
{
return reflective.getName();
}
public String arrayComponentName()
|
|{
|
|return "L" + classloaderName() + ";";
}
/**
* Return an unmodifiable list of the type parameters applied to the
* innermost class in this generic type.
*/
public List<? extends GenTypeParameter> getTypeParamList()
|
|{
|
|if (params == null)
|
|return Collections.emptyList();
|
|else{ return params;
|
|}
|
|}
|
|/**
| Get the containing type. If this is a generic type whose class is an
| inner class, and an outer class is also generic, this will return the
| outer class of the class type. NOTE, it will not necessarily work if
| no outer class is generic, or if this is a raw type!
|
public GenTypeClass getOuterType()
{
return outer;
}
| Determine whether this class is an inner type. This works regardless
| of whether outer types are generic etc.
|
public boolean isInnerType()
{
return reflective.getName().indexOf('$') != -1;
}
| Check whether the type is a generic type (with type parameters).
| Returns false for parameterless types and raw types.
|
| @return true if the type has type parameters
|
public boolean isGeneric()
{
if (outer != null)
return true;
else{ return (params != null);
}
}
| Check whether this is a raw type, ie. a generic class type with no
| type parameter substitutions supplied. (Return is false for a non-
| generic class type).
|
| @return true if the type is a raw type
|
public boolean isRaw()
{
if (outer != null || params != null) {
return false;
}
Reflective r = reflective;
List<?> formalParams = reflective.getTypeParams();
while (formalParams.isEmpty()){
if (r.isStatic()) {
return false;
}
r = r.getOuterClass();
if (r == null) {
return false;
}
formalParams = r.getTypeParams();
}
return true;
}
public boolean isInterface()
{
return reflective.isInterface();
}
public String toString(NameTransform nt)
{
String baseClass = classloaderName();
if (outer != null) {
int i = baseClass.lastIndexOf('$');
baseClass = outer.toString(nt) + '.' + baseClass.substring(i + 1);
}
else {
baseClass = nt.transform(baseClass);
baseClass = baseClass.replace('$', '.');
}
if (params == null)
return baseClass;
String r = baseClass + '<';
for (Iterator<? extends GenTypeParameter> i = params.iterator(); i.hasNext(); ) {
r += i.next().toTypeArgString(nt);
if ( i.hasNext() )
r += ',';
}
r += '>';
return r;
}
public String toTypeArgString(NameTransform nt)
{
return toString(nt);
}
public boolean equals(JavaType other)
{
if (other == this)
return true;
if (other == null)
return false;
GenTypeClass oClass = other.asClass();
if (oClass == null) {
return false;
}
JavaType arrayComponent = getArrayComponent();
JavaType oarrayComponent = oClass.getArrayComponent();
if (arrayComponent != null) {
return arrayComponent.equals(oarrayComponent);
}
else if (oarrayComponent != null) {
return false;
}
if (! classloaderName().equals(oClass.classloaderName()))
return false;
if (outer == null && oClass.outer != null)
return false;
if (outer != null)
if (! outer.equals(oClass.outer))
return false;
if (params == null) {
return oClass.params == null;
}
else if (oClass.params == null) {
return false;
}
Iterator<? extends GenTypeParameter> i = params.iterator();
Iterator<? extends GenTypeParameter> j = oClass.params.iterator();
while ( i.hasNext() ) {
if ( ! j.hasNext() || ! i.next().equals(j.next())) {
return false;
}
}
if ( j.hasNext() )
return false;
return true;
}
| Get the reflective represented by this GenTypeClass. This can return null
| if the GenTypeClass represents an array.
|
public Reflective getReflective()
{
return reflective;
}
|
| Note this does not handle boxing/unboxing conversions.
|
| (non-Javadoc)
| @see bluej.debugger.gentype.JavaType#isAssignableFrom(bluej.debugger.gentype.JavaType)
|
public boolean isAssignableFrom(JavaType t)
{
if (t.isNull())
return true;
if (! (t instanceof GenTypeSolid) )
return false;
GenTypeClass tc = t.asClass();
if (tc != null) {
if (isRaw()) {
return reflective.isAssignableFrom(tc.reflective);
}
GenTypeClass cclass = this;
GenTypeClass tclass;
try {
tclass = tc.mapToSuper(reflective.getName());
}
catch (BadInheritanceChainException bice) {
return false;
}
if (tclass.isRaw())
return false;
while (cclass != null){
if (cclass.params != null) {
Iterator<? extends GenTypeParameter> i = cclass.params.iterator();
Iterator<? extends GenTypeParameter> j = tclass.params.iterator();
while (i.hasNext()){
GenTypeParameter cpar = i.next();
GenTypeParameter tpar = j.next();
if (! cpar.contains(tpar))
return false;
}
}
cclass = cclass.outer;
tclass = tclass.outer;
}
return true;
}
GenTypeClass [] stypes = ((GenTypeSolid) t).getReferenceSupertypes();
for (int i = 0; i < stypes.length; i++) {
if (isAssignableFrom(stypes[i]))
return true;
}
return false;
}
public boolean isAssignableFrom(GenTypeClass c)
{
Reflective r = c.reflective;
if ( getInheritanceChain(r, reflective.getName()) != null) {
GenTypeClass other = c.mapToSuper(reflective.getName());
if (isRaw() || other.isRaw())
return true;
if (outer != null) {
if (! outer.isAssignableFrom(other.outer))
return false;
}
if (params != null) {
Iterator<? extends GenTypeParameter> i = params.iterator();
Iterator<? extends GenTypeParameter> j = other.params.iterator();
while (i.hasNext()){
GenTypeParameter myParam = i.next();
GenTypeParameter oParam = j.next();
if (! myParam.contains(oParam))
return false;
}
}
return true;
}
return false;
}
public boolean isAssignableFromRaw(JavaType t)
{
if (! (t instanceof GenTypeClass))
return false;
GenTypeClass c = (GenTypeClass) t;
Reflective r = c.reflective;
if ( getInheritanceChain(r, reflective.getName()) != null)
return true;
else{ return false;
}
}
| Map the type parameters in a base type to a super type, apply the
| resulting type parameters to the super type, and return the result.
|
| For instance, if A<T> extends B<U>, Then to map an instance
| of A<Integer> to B, pass "B" as the super type; The return is
|* then B<Integer>.
*
* @param subType the supertype to map from
* @param basename the fully-qualified name of the base type to map to
*
* @throws BadInheritanceChainException
public GenTypeClass mapToSuper(String basename)
{
if ( classloaderName().equals(basename))
return this;
Stack<Reflective> inheritanceStack = getInheritanceChain(reflective, basename);
if ( inheritanceStack == null ) {
throw new BadInheritanceChainException();
}
String bname;
Iterator<Reflective> i = inheritanceStack.iterator();
i.next();
Reflective baseType;
Reflective subType = reflective;
GenTypeClass ccc = this;
do {
baseType = (Reflective)i.next();
bname = baseType.getName();
Map<String,GenTypeParameter> tparams = ccc.getMap();
ccc = mapGenericParamsToDirectBase(tparams, subType, baseType);
subType = baseType;
} while ( ! bname.equals(basename) );
return ccc;
}
| Worker function for mapGenericParamsToBase. Maps only to a direct base.
| @param tparams a Map of String -> GenTypeClass
| @param subType the derived type
| @param baseType the base type
|
private static GenTypeClass mapGenericParamsToDirectBase(Map<String,? extends GenTypeParameter> tparams,
Reflective subType, Reflective baseType)
{
GenTypeClass baseClass = subType.superTypeByName(baseType.getName());
if (tparams == null) {
return new GenTypeClass(baseClass.reflective);
}
baseClass = (GenTypeClass) baseClass.mapTparsToTypes(tparams);
return baseClass;
}
| Return the corresponding type if all type parameters are replaced with
| corresponding actual types, as defined by a Map (String -> GenType).
|
| @param tparams A map defining the translation from type parameter
| name (String) to its actual type (GenType). The map
| can be null to return the raw type.
| @return the corresponding type structure, with parameters mapped.
|
public GenTypeClass mapTparsToTypes(Map<String, ? extends GenTypeParameter> tparams)
{
if ( params == null && outer == null )
return this;
if (tparams == null) {
return new GenTypeClass(reflective);
}
List<GenTypeParameter> retlist = new ArrayList<GenTypeParameter>();
if (params != null) {
Iterator<? extends GenTypeParameter> i = params.iterator();
while ( i.hasNext() ) {
retlist.add(i.next().mapTparsToTypes(tparams));
}
}
GenTypeClass newOuter = null;
if (outer != null) {
newOuter = (GenTypeClass) outer.mapTparsToTypes(tparams);
}
return new GenTypeClass(reflective, retlist, newOuter);
}
public GenTypeClass mapToDerived(Reflective derivedType)
{
if (! isGeneric() )
return new GenTypeClass(derivedType);
if ( derivedType.getName().equals(classloaderName()))
return this;
Stack<Reflective> classes = getInheritanceChain(derivedType, classloaderName());
if ( classes == null )
return null;
GenTypeClass curBaseC = this;
classes.pop();
while ( ! classes.empty() ) {
Reflective curSubtype = (Reflective)classes.pop();
HashMap<String,GenTypeParameter> newMap = new HashMap<String,GenTypeParameter>();
GenTypeClass baseDecl = curSubtype.superTypeByName(curBaseC.classloaderName());
if (baseDecl.isRaw()) {
return new GenTypeClass(derivedType);
}
baseDecl.getParamsFromTemplate(newMap, curBaseC);
curBaseC = new GenTypeClass(curSubtype, newMap);
}
return curBaseC;
}
| Get a map of type parameter names to the corresponding types, for this
| type. The returned map is a mutable copy, that is, it can freely be
| modified by the caller without affecting this GenTypeClass object.
|
| <p>Returns null if this represents a raw type, or an empty map if the
| type is not a generic type.
|
| <p>Note that a map is not enough to completely describe a type, due to
| the possibility of inner/outer types having type parameters with the
| same name.
|
| @return the map (of String -> GenTypeParameterizable).
|
public Map getMap()
{
if (isRaw()) {
return null;
}
HashMap<String,GenTypeParameter> r = new HashMap<String,GenTypeParameter>();
mergeMap(r);
return r;
}
| Get a map of type parameter names to the corresponding types, for this
| type. Existing entries in the map will be overwritten.
|
| The returned does not indicate if this type is a raw type.
|
public void mergeMap(Map<String, GenTypeParameter> m)
{
if (outer != null)
{
outer.mergeMap(m);
}
List<GenTypeDeclTpar> formalParams = reflective.getTypeParams();
if ( params == null )
{
return;
}
Iterator<? extends GenTypeParameter> paramIterator = params.iterator();
Iterator<GenTypeDeclTpar> formalIterator = formalParams.iterator();
while (paramIterator.hasNext() && formalIterator.hasNext())
{
GenTypeParameter paramType = paramIterator.next();
GenTypeDeclTpar formalType = (GenTypeDeclTpar)formalIterator.next();
String paramName = formalType.getTparName();
m.put(paramName, paramType);
}
}
| Determine the inheritance, or implementation chain between two different
| types. For instance, if A extends B and B extends C, the chain between
| A and C is "A,B,C". Likewise, if D implements E which extends F, the
|* chain between D and F is "D,E,F".
*
* returns a Stack of Reflective.
*/
private static Stack<Reflective> getInheritanceChain(Reflective top, String bottom)
{
Stack<Reflective> r = new Stack<Reflective>();
r.push(top);
|
|if ( top.getName().equals(bottom )) {
|
|return r;
|
|}
|
|// Go through each base/interface and try to discover the hieararchy
|
|List<Reflective> l = top.getSuperTypesR();
|
|for (Iterator<Reflective> i = l.iterator(); i.hasNext(); ) {
|
|Reflective next = i.next();
|
|Stack<Reflective> r2 = getInheritanceChain(next, bottom);
|
|if ( r2 != null ) {
|
|r.addAll(r2);
|
|return r;
|
|}
|
|}
|
|return null;
|
|}
|
|/*
| see bluej.debugger.gentype.GenTypeSolid#getParamsFromTemplate(java.util.Map, bluej.debugger.gentype.GenTypeParameterizable)
|
public void getParamsFromTemplate(Map<String,GenTypeParameter> r, GenTypeParameter template)
{
if (template instanceof GenTypeClass) {
GenTypeClass classTemplate = (GenTypeClass) template;
if (classTemplate.classloaderName().equals(classloaderName())) {
if (params == null || classTemplate.params == null)
return;
Iterator<? extends GenTypeParameter> i = params.iterator();
Iterator<? extends GenTypeParameter> j = classTemplate.params.iterator();
if (outer != null)
outer.getParamsFromTemplate(r, classTemplate.outer);
while (i.hasNext() && j.hasNext()){
GenTypeSolid ip = (GenTypeSolid) i.next();
GenTypeParameter jp = j.next();
ip.getParamsFromTemplate(r, jp);
}
}
}
return;
}
public void erasedSuperTypes(Set<Reflective> s)
{
Stack<Reflective> refs = new Stack<Reflective>();
refs.push(reflective);
while (! refs.empty()) {
Reflective r = (Reflective) refs.pop();
if (! s.contains(r)) {
s.add(r);
refs.addAll(r.getSuperTypesR());
}
}
}
public GenTypeClass [] getReferenceSupertypes()
{
return new GenTypeClass[] {this
};
}
@Override
public GenTypeClass getArray()
{
return new GenTypeArrayClass(reflective.getArrayOf(), this);
}
@Override
public GenTypeClass getCapture()
{
if (outer == null && params == null) {
return this;
}
GenTypeClass outerCapture = outer == null ? null : outer.getCapture();
boolean isDifferent = outerCapture != outer;
List<JavaType> capturedParams = null;
if (params != null) {
capturedParams = new ArrayList<JavaType>(params.size());
for (GenTypeParameter param : params) {
JavaType captured = param.getTparCapture();
isDifferent |= captured != param;
capturedParams.add(captured);
}
}
if (isDifferent) {
return new GenTypeClass(reflective, capturedParams, outerCapture);
}
return this;
}
}
. GenTypeClass
. GenTypeClass
. GenTypeClass
. GenTypeClass
. asClass
. getErasedType
. getOuterType
. isInnerType
. isGeneric
. isRaw
. isInterface
. toString
. toTypeArgString
. equals
. getReflective
. isAssignableFrom
. isAssignableFrom
. isAssignableFromRaw
. mapToSuper
. mapGenericParamsToDirectBase
. mapTparsToTypes
. mapToDerived
. getMap
. mergeMap
. getParamsFromTemplate
. erasedSuperTypes
. getReferenceSupertypes
. getArray
. getCapture
793 neLoCode
+ 99 LoComm