package com.fasterxml.classmate.types;
import java.lang.reflect.Modifier;
import java.util.*;
import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.classmate.TypeBindings;
import com.fasterxml.classmate.members.RawConstructor;
import com.fasterxml.classmate.members.RawField;
import com.fasterxml.classmate.members.RawMethod;
Specialized type placeholder used in cases where type definition is
recursive; to avoid infinite loop, reference that would be "back" in
hierarchy is represented by an instance of this class.
Underlying information is achievable (for full resolution), but
not exposed using super type (parent) accessors; and has special
handling when used for constructing descriptions.
/**
* Specialized type placeholder used in cases where type definition is
* recursive; to avoid infinite loop, reference that would be "back" in
* hierarchy is represented by an instance of this class.
* Underlying information is achievable (for full resolution), but
* not exposed using super type (parent) accessors; and has special
* handling when used for constructing descriptions.
*/
public class ResolvedRecursiveType extends ResolvedType
{
Actual fully resolved type; assigned once resolution is complete
/**
* Actual fully resolved type; assigned once resolution is complete
*/
protected ResolvedType _referencedType;
/*
/**********************************************************************
/* Life cycle
/**********************************************************************
*/
public ResolvedRecursiveType(Class<?> erased, TypeBindings bindings)
{
super(erased, bindings);
}
@Override
public boolean canCreateSubtypes() {
return _referencedType.canCreateSubtypes();
}
public void setReference(ResolvedType ref)
{
// sanity check; should not be called multiple times
if (_referencedType != null) {
throw new IllegalStateException("Trying to re-set self reference; old value = "+_referencedType+", new = "+ref);
}
_referencedType = ref;
}
/*
/**********************************************************************
/* Accessors for related types
/**********************************************************************
*/
To avoid infinite loops, will return null;
/**
* To avoid infinite loops, will return null;
*/
@Override
public ResolvedType getParentClass() {
return null;
}
@Override
public ResolvedType getSelfReferencedType() { return _referencedType; }
To avoid infinite loops, will return empty list
/**
* To avoid infinite loops, will return empty list
*/
@Override
public List<ResolvedType> getImplementedInterfaces() {
return Collections.<ResolvedType>emptyList();
}
To avoid infinite loops, will return null type
/**
* To avoid infinite loops, will return null type
*/
@Override
public ResolvedType getArrayElementType() { // interfaces are never arrays, so:
return null;
}
/*
/**********************************************************************
/* Simple property accessors
/**********************************************************************
*/
@Override
public boolean isInterface() { return _erasedType.isInterface(); }
@Override
public boolean isAbstract() { return Modifier.isAbstract(_erasedType.getModifiers()); }
@Override
public boolean isArray() { return _erasedType.isArray(); }
@Override
public boolean isPrimitive() { return false; }
/*
/**********************************************************************
/* Accessors for raw (minimally procesed) members
/**********************************************************************
*/
@Override
public List<RawField> getMemberFields() { return _referencedType.getMemberFields(); }
@Override
public List<RawField> getStaticFields() { return _referencedType.getStaticFields(); }
@Override
public List<RawMethod> getStaticMethods() { return _referencedType.getStaticMethods(); }
@Override
public List<RawMethod> getMemberMethods() { return _referencedType.getMemberMethods(); }
@Override
public List<RawConstructor> getConstructors() { return _referencedType.getConstructors(); }
/*
/**********************************************************************
/* String representations
/**********************************************************************
*/
@Override
public StringBuilder appendSignature(StringBuilder sb) {
// to avoid infinite recursion, only print type erased version
return appendErasedSignature(sb);
}
@Override
public StringBuilder appendErasedSignature(StringBuilder sb) {
return _appendErasedClassSignature(sb);
}
@Override
public StringBuilder appendBriefDescription(StringBuilder sb) {
return _appendClassDescription(sb);
}
@Override
public StringBuilder appendFullDescription(StringBuilder sb)
{
// should never get called, but just in case, only print brief description
return appendBriefDescription(sb);
}
/*
/**********************************************************************
/* Other overrides
/**********************************************************************
*/
@Override public boolean equals(Object o)
{
if (!super.equals(o)) {
return false;
}
// not sure if we should match at all, but definitely need this
// additional part if we do:
ResolvedRecursiveType other = (ResolvedRecursiveType) o;
if (_referencedType == null) {
return other._referencedType == null;
}
return _referencedType.equals(other._referencedType);
}
}