AnnotatedClass.java
package tools.jackson.databind.introspect;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.*;
import java.util.stream.Stream;
import tools.jackson.databind.JavaType;
import tools.jackson.databind.cfg.MapperConfig;
import tools.jackson.databind.type.TypeBindings;
import tools.jackson.databind.util.Annotations;
import tools.jackson.databind.util.ClassUtil;
public final class AnnotatedClass
extends Annotated
implements TypeResolutionContext
{
private final static Creators NO_CREATORS = new Creators(null,
Collections.<AnnotatedConstructor>emptyList(),
Collections.<AnnotatedMethod>emptyList());
/*
/**********************************************************
/* Configuration
/**********************************************************
*/
protected final MapperConfig<?> _config;
/**
* Resolved Java type for which information is collected: also works as
* context for resolving possible generic type of accessors declared in this
* type.
*/
protected final JavaType _type;
/**
* Type erased {@link Class} matching {@code _type}.
*/
protected final Class<?> _class;
/**
* Type bindings to use for members of {@link #_class}.
*/
protected final TypeBindings _bindings;
/**
* Ordered set of super classes and interfaces of the
* class itself: included in order of precedence
*/
protected final List<JavaType> _superTypes;
/**
* Object that knows mapping of mix-in classes (ones that contain
* annotations to add) with their target classes (ones that
* get these additional annotations "mixed in").
*/
protected final MixInResolver _mixInResolver;
/**
* Primary mix-in class; one to use for the annotated class
* itself. Can be null.
*/
protected final Class<?> _primaryMixIn;
/**
* Flag that indicates whether (full) annotation resolution should
* occur: is disabled for all JDK types.
*/
protected final boolean _collectAnnotations;
/*
/**********************************************************************
/* Gathered information
/**********************************************************************
*/
/**
* Combined list of Jackson annotations that the class has,
* including inheritable ones from super classes and interfaces
*/
protected final Annotations _classAnnotations;
protected Creators _creators;
/**
* Member methods of interest; for now ones with 0 or 1 arguments
* (just optimization, since others won't be used now)
*/
protected AnnotatedMethodMap _memberMethods;
/**
* Member fields of interest: ones that are either public,
* or have at least one annotation.
*/
protected List<AnnotatedField> _fields;
/**
* Lazily determined property to see if this is a non-static inner
* class.
*/
protected transient Boolean _nonStaticInnerClass;
/*
/**********************************************************************
/* Life-cycle
/**********************************************************************
*/
/**
* Constructor will not do any initializations, to allow for
* configuring instances differently depending on use cases
*
* @param type Fully resolved type; may be `null`, but ONLY if no member fields or
* methods are to be accessed
* @param rawType Type-erased class; pass if no `type` needed or available
*/
AnnotatedClass(MapperConfig<?> config, JavaType type, Class<?> rawType, List<JavaType> superTypes,
Class<?> primaryMixIn, Annotations classAnnotations, TypeBindings bindings,
MixInResolver mir, boolean collectAnnotations)
{
_config = config;
// 27-May-2025, tatu: May be `null`, alas (for "resolveWithoutSuperTypes()" mostly)
_type = type;
_class = rawType;
_superTypes = superTypes;
_primaryMixIn = primaryMixIn;
_classAnnotations = (classAnnotations == null)
? AnnotationCollector.emptyAnnotations() : classAnnotations;
_bindings = bindings;
_mixInResolver = mir;
_collectAnnotations = collectAnnotations;
}
/**
* Constructor (only) used for creating primordial simple types (during bootstrapping)
* and array type placeholders where no fields or methods are needed.
*/
AnnotatedClass(Class<?> rawType) {
_config = null;
_type = null;
_class = rawType;
_superTypes = Collections.emptyList();
_primaryMixIn = null;
_classAnnotations = AnnotationCollector.emptyAnnotations();
_bindings = TypeBindings.emptyBindings();
_mixInResolver = null;
_collectAnnotations = false;
// And pre-set accessors:
_creators = NO_CREATORS;
_fields = Collections.emptyList();
_memberMethods = new AnnotatedMethodMap();
}
/*
/**********************************************************************
/* TypeResolutionContext implementation
/**********************************************************************
*/
@Override
public JavaType resolveType(Type type) {
return _config.getTypeFactory().resolveMemberType(type, _bindings);
}
/*
/**********************************************************************
/* Annotated impl
/**********************************************************************
*/
@Override
public Class<?> getAnnotated() { return _class; }
@Override
public int getModifiers() { return _class.getModifiers(); }
@Override
public String getName() { return _class.getName(); }
@Override
public <A extends Annotation> A getAnnotation(Class<A> acls) {
return _classAnnotations.get(acls);
}
@Override
public boolean hasAnnotation(Class<? extends Annotation> acls) {
return _classAnnotations.has(acls);
}
@Override
public boolean hasOneOf(Class<? extends Annotation>[] annoClasses) {
return _classAnnotations.hasOneOf(annoClasses);
}
@Override
public Stream<Annotation> annotations() {
return _classAnnotations.values();
}
@Override
public Class<?> getRawType() {
return _class;
}
@Override
public JavaType getType() {
return _type;
}
/*
/**********************************************************************
/* Public API, generic accessors
/**********************************************************************
*/
public Annotations getAnnotations() {
return _classAnnotations;
}
public boolean hasAnnotations() {
return _classAnnotations.size() > 0;
}
public AnnotatedConstructor getDefaultConstructor() {
return _creators().defaultConstructor;
}
public List<AnnotatedConstructor> getConstructors() {
return _creators().constructors;
}
public List<AnnotatedMethod> getFactoryMethods() {
return _creators().creatorMethods;
}
public Iterable<AnnotatedMethod> memberMethods() {
return _methods();
}
public int getMemberMethodCount() {
return _methods().size();
}
public AnnotatedMethod findMethod(String name, Class<?>[] paramTypes) {
return _methods().find(name, paramTypes);
}
public int getFieldCount() {
return _fields().size();
}
public Iterable<AnnotatedField> fields() {
return _fields();
}
public boolean isNonStaticInnerClass()
{
Boolean B = _nonStaticInnerClass;
if (B == null) {
_nonStaticInnerClass = B = ClassUtil.isNonStaticInnerClass(_class);
}
return B.booleanValue();
}
/*
/**********************************************************************
/* Lazily-operating accessors
/**********************************************************************
*/
private final List<AnnotatedField> _fields() {
List<AnnotatedField> f = _fields;
if (f == null) {
// 09-Jun-2017, tatu: _type null for cases where we do not want
// introspection (and primordial types)
if (_type == null) {
f = Collections.emptyList();
} else {
f = AnnotatedFieldCollector.collectFields(_config,
this, _mixInResolver,
_type, _primaryMixIn, _collectAnnotations);
}
}
return f;
}
private final AnnotatedMethodMap _methods() {
AnnotatedMethodMap m = _memberMethods;
if (m == null) {
// 09-Jun-2017, tatu: _type null for cases where we do not want
// introspection (and primordial types)
// NOTE: would be great to have light-weight shareable maps; no such impl exists for now
if (_type == null) {
m = new AnnotatedMethodMap();
} else {
m = AnnotatedMethodCollector.collectMethods(_config,
this, _mixInResolver,
_type, _superTypes, _primaryMixIn, _collectAnnotations);
}
_memberMethods = m;
}
return m;
}
private final Creators _creators() {
Creators c = _creators;
if (c == null) {
c = AnnotatedCreatorCollector.collectCreators(_config,
this, _type, _primaryMixIn, _collectAnnotations);
_creators = c;
}
return c;
}
/*
/**********************************************************************
/* Standard method overrides
/**********************************************************************
*/
@Override
public String toString() {
return "[AnnotedClass "+_class.getName()+"]";
}
@Override
public int hashCode() {
return _class.hashCode();
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!ClassUtil.hasClass(o, getClass())) {
return false;
}
return ((AnnotatedClass) o)._class == _class;
}
/*
/**********************************************************************
/* Helper classes
/**********************************************************************
*/
public static final class Creators
{
/**
* Default constructor of the annotated class, if it has one.
*/
public final AnnotatedConstructor defaultConstructor;
/**
* Single argument constructors the class has, if any.
*/
public final List<AnnotatedConstructor> constructors;
/**
* Single argument static methods that might be usable
* as factory methods
*/
public final List<AnnotatedMethod> creatorMethods;
public Creators(AnnotatedConstructor defCtor,
List<AnnotatedConstructor> ctors,
List<AnnotatedMethod> ctorMethods)
{
defaultConstructor = defCtor;
constructors = ctors;
creatorMethods = ctorMethods;
}
}
}