BeanDescription.java
package tools.jackson.databind;
import java.util.*;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import tools.jackson.databind.cfg.MapperConfig;
import tools.jackson.databind.introspect.*;
import tools.jackson.databind.util.Annotations;
/**
* Basic container for information gathered by {@link ClassIntrospector} to
* help in constructing serializers and deserializers.
* Note that the one implementation type is
* {@link tools.jackson.databind.introspect.BasicBeanDescription},
* meaning that it is safe to upcast to that type.
*/
public abstract class BeanDescription
{
/**
* Bean type information, including raw class and possible
* generics information
*/
protected final JavaType _type;
/*
/**********************************************************************
/* Life-cycle
/**********************************************************************
*/
protected BeanDescription(JavaType type) {
_type = type;
}
/**
* Method for constructing a supplier for this bean description instance:
* sometimes needed when code expects supplier, not description instance.
*/
public abstract BeanDescription.Supplier supplier();
/*
/**********************************************************************
/* Simple accessors
/**********************************************************************
*/
/**
* Method for accessing declared type of bean being introspected,
* including full generic type information (from declaration)
*/
public JavaType getType() { return _type; }
public Class<?> getBeanClass() { return _type.getRawClass(); }
public boolean isRecordType() { return _type.isRecordType(); }
public boolean isNonStaticInnerClass() {
return getClassInfo().isNonStaticInnerClass();
}
/**
* Method for accessing low-level information about Class this
* item describes.
*/
public abstract AnnotatedClass getClassInfo();
/**
* Accessor for getting information about Object Id expected to
* be used for this POJO type, if any.
*/
public abstract ObjectIdInfo getObjectIdInfo();
/**
* Method for checking whether class being described has any
* annotations recognized by registered annotation introspector.
*/
public abstract boolean hasKnownClassAnnotations();
/**
* Method for accessing collection of annotations the bean
* class has.
*/
public abstract Annotations getClassAnnotations();
/*
/**********************************************************************
/* Basic API for finding properties
/**********************************************************************
*/
/**
* @return Ordered Map with logical property name as key, and
* matching getter method as value.
*/
public abstract List<BeanPropertyDefinition> findProperties();
public abstract Set<String> getIgnoredPropertyNames();
/**
* Method for locating all back-reference properties (setters, fields) bean has
*/
public abstract List<BeanPropertyDefinition> findBackReferences();
/*
/**********************************************************************
/* Basic API for finding Creators, related information
/**********************************************************************
*/
/**
* Helper method that will return all non-default constructors (that is,
* constructors that take one or more arguments) this class has.
*/
public abstract List<AnnotatedConstructor> getConstructors();
/**
* Method similar to {@link #getConstructors()} except will also introspect
* {@code JsonCreator.Mode} and filter out ones marked as not applicable and
* include mode (or lack thereof) for remaining constructors.
*<p>
* Note that no other filtering (regarding visibility or other annotations)
* is performed
*
* @since 2.13
*/
public abstract List<AnnotatedAndMetadata<AnnotatedConstructor, JsonCreator.Mode>> getConstructorsWithMode();
/**
* Helper method that will check all static methods of the bean class
* that seem like factory methods eligible to be used as Creators.
* This requires that the static method:
*<ol>
* <li>Returns type compatible with bean type (same or subtype)
* </li>
* <li>Is recognized from either explicit annotation (usually {@code @JsonCreator}
* OR naming:
* names {@code valueOf()} and {@code fromString()} are recognized but
* only for 1-argument factory methods, and in case of {@code fromString()}
* argument type must further be either {@code String} or {@code CharSequence}.
* </li>
*</ol>
* Note that caller typically applies further checks for things like visibility.
*
* @return List of static methods considered as possible Factory methods
*/
public abstract List<AnnotatedMethod> getFactoryMethods();
/**
* Method similar to {@link #getFactoryMethods()} but will return {@code JsonCreator.Mode}
* metadata along with qualifying factory method candidates.
*
* @since 2.13
*/
public abstract List<AnnotatedAndMetadata<AnnotatedMethod, JsonCreator.Mode>> getFactoryMethodsWithMode();
/**
* Method that will locate the no-arg constructor for this class,
* if it has one, and that constructor has not been marked as
* ignorable.
*/
public abstract AnnotatedConstructor findDefaultConstructor();
/**
* Method that is replacing earlier Creator introspection access methods.
*
* @since 2.18
*
* @return Container for introspected Creator candidates, if any
*/
public abstract PotentialCreators getPotentialCreators();
/*
/**********************************************************************
/* Basic API for finding property accessors
/**********************************************************************
*/
/**
* Method for locating accessor (readable field, or "getter" method)
* that has
* {@link com.fasterxml.jackson.annotation.JsonKey} annotation,
* if any. If multiple ones are found,
* an error is reported by throwing {@link IllegalArgumentException}
*/
public AnnotatedMember findJsonKeyAccessor() {
return null;
}
/**
* Method for locating accessor (readable field, or "getter" method)
* that has
* {@link com.fasterxml.jackson.annotation.JsonValue} annotation,
* if any. If multiple ones are found,
* an error is reported by throwing {@link IllegalArgumentException}
*/
public abstract AnnotatedMember findJsonValueAccessor();
/**
* Method used to locate the Method or Field of introspected class that
* is annotated with {@link com.fasterxml.jackson.annotation.JsonAnyGetter}
* (or equivalent annotation).
* If no such {@code AnnotatedMember} exists {@code null} is returned.
* If more than one are found, an exception is thrown.
*/
public abstract AnnotatedMember findAnyGetter();
/**
* Method used to locate a mutator (settable field, or 2-argument set method)
* of introspected class that
* is annotated with {@link com.fasterxml.jackson.annotation.JsonAnySetter}
* (or equivalent annotation).
* If no such mutator exists {@code null} is returned.
* If more than one are found an exception is thrown.
* Additional checks are also made to see that method signature
* is acceptable: needs to take 2 arguments, first one String or
* Object; second any can be any type.
*/
public abstract AnnotatedMember findAnySetterAccessor();
public abstract AnnotatedMethod findMethod(String name, Class<?>[] paramTypes);
/*
/**********************************************************************
/* Basic API, class configuration
/**********************************************************************
*/
/**
* Method for finding annotation-indicated inclusion definition (if any);
* possibly overriding given default value.
*<p>
* NOTE: does NOT use global inclusion default settings as the base, unless
* passed as `defValue`.
*/
public abstract JsonInclude.Value findPropertyInclusion(JsonInclude.Value defValue);
/*
/**********************************************************************
/* Basic API, other
/**********************************************************************
*/
public abstract Map<Object, AnnotatedMember> findInjectables();
/**
* Method called to create a "default instance" of the bean, currently
* only needed for obtaining default field values which may be used for
* suppressing serialization of fields that have "not changed".
*
* @param fixAccess If true, method is allowed to fix access to the
* default constructor (to be able to call non-public constructor);
* if false, has to use constructor as is.
*
* @return Instance of class represented by this descriptor, if
* suitable default constructor was found; null otherwise.
*/
public abstract Object instantiateBean(boolean fixAccess);
/**
* Method for finding out if the POJO specifies default view(s) to
* use for properties, considering both per-type annotations and
* global default settings.
*/
public abstract Class<?>[] findDefaultViews();
/**
* Interface for lazily-constructed suppliers for {@link BeanDescription} instances;
* extends plain {@link java.util.function.Supplier} with convenience accessors.
*/
public interface Supplier extends java.util.function.Supplier<BeanDescription>
{
@Override
public BeanDescription get();
Annotations getClassAnnotations();
Class<?> getBeanClass();
AnnotatedClass getClassInfo();
JavaType getType();
boolean isRecordType();
JsonFormat.Value findExpectedFormat(Class<?> baseType);
}
protected static abstract class SupplierBase implements Supplier
{
protected final MapperConfig<?> _config;
protected final JavaType _type;
/**
* Format definitions lazily introspected from class annotations
*/
protected transient JsonFormat.Value _classFormat;
protected SupplierBase(MapperConfig<?> config, JavaType type) {
_config = config;
_type = type;
}
// // Simple accessors:
@Override
public JavaType getType() { return _type; }
@Override
public Class<?> getBeanClass() { return _type.getRawClass(); }
@Override
public boolean isRecordType() { return _type.isRecordType(); }
// // // Introspection
@Override
public JsonFormat.Value findExpectedFormat(Class<?> baseType)
{
JsonFormat.Value v0 = _classFormat;
if (v0 == null) { // copied from above
v0 = _config.getAnnotationIntrospector().findFormat(_config,
getClassInfo());
if (v0 == null) {
v0 = JsonFormat.Value.empty();
}
_classFormat = v0;
}
JsonFormat.Value v1 = _config.getDefaultPropertyFormat(baseType);
if (v1 == null) {
return v0;
}
return JsonFormat.Value.merge(v0, v1);
}
}
/**
* Partial implementation for lazily-constructed suppliers for {@link BeanDescription} instances.
*/
public static abstract class LazySupplier extends SupplierBase
{
protected transient AnnotatedClass _classDesc;
protected transient BeanDescription _beanDesc;
protected LazySupplier(MapperConfig<?> config, JavaType type) {
super(config, type);
}
// // Entity accessors:
@Override
public Annotations getClassAnnotations() {
return getClassInfo().getAnnotations();
}
@Override
public AnnotatedClass getClassInfo() {
if (_classDesc == null) {
_classDesc = _introspect(_type);
}
return _classDesc;
}
@Override
public BeanDescription get() {
if (_beanDesc == null) {
// To test without caching, uncomment:
//return _construct(_type, getClassInfo());
_beanDesc = _construct(_type, getClassInfo());
}
return _beanDesc;
}
// // // Internal factory methods
protected abstract AnnotatedClass _introspect(JavaType forType);
protected abstract BeanDescription _construct(JavaType forType, AnnotatedClass ac);
}
/**
* Simple {@link Supplier} implementation that just returns pre-constructed
* {@link BeanDescription} instance.
*/
public static class EagerSupplier extends SupplierBase
{
protected final BeanDescription _beanDesc;
public EagerSupplier(MapperConfig<?> config, BeanDescription beanDesc) {
super(config, beanDesc.getType());
_beanDesc = beanDesc;
}
@Override
public BeanDescription get() { return _beanDesc; }
@Override
public AnnotatedClass getClassInfo() {
return _beanDesc.getClassInfo();
}
@Override
public Annotations getClassAnnotations() {
return _beanDesc.getClassAnnotations();
}
}
}