com.fasterxml.jackson.databind.introspect.AnnotatedClassResolver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ehcache Show documentation
Show all versions of ehcache Show documentation
Ehcache is an open source, standards-based cache used to boost performance,
offload the database and simplify scalability. Ehcache is robust, proven and full-featured and
this has made it the most widely-used Java-based cache.
package com.fasterxml.jackson.databind.introspect;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.Collections;
import java.util.List;
import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.ClassIntrospector.MixInResolver;
import com.fasterxml.jackson.databind.type.TypeBindings;
import com.fasterxml.jackson.databind.util.Annotations;
import com.fasterxml.jackson.databind.util.ClassUtil;
/**
* Helper class that contains logic for resolving annotations to construct
* {@link AnnotatedClass} instances.
*
* @since 2.9
*/
public class AnnotatedClassResolver
{
private final static Annotations NO_ANNOTATIONS = AnnotationCollector.emptyAnnotations();
private final MapperConfig> _config;
private final AnnotationIntrospector _intr;
private final MixInResolver _mixInResolver;
private final TypeBindings _bindings;
private final JavaType _type;
private final Class> _class;
private final Class> _primaryMixin;
AnnotatedClassResolver(MapperConfig> config, JavaType type, MixInResolver r) {
_config = config;
_type = type;
_class = type.getRawClass();
_mixInResolver = r;
_bindings = type.getBindings();
_intr = config.isAnnotationProcessingEnabled()
? config.getAnnotationIntrospector() : null;
_primaryMixin = _config.findMixInClassFor(_class);
}
AnnotatedClassResolver(MapperConfig> config, Class> cls, MixInResolver r) {
_config = config;
_type = null;
_class = cls;
_mixInResolver = r;
_bindings = TypeBindings.emptyBindings();
if (config == null) {
_intr = null;
_primaryMixin = null;
} else {
_intr = config.isAnnotationProcessingEnabled()
? config.getAnnotationIntrospector() : null;
_primaryMixin = _config.findMixInClassFor(_class);
}
}
public static AnnotatedClass resolve(MapperConfig> config, JavaType forType,
MixInResolver r)
{
if (forType.isArrayType() && skippableArray(config, forType.getRawClass())) {
return createArrayType(config, forType.getRawClass());
}
return new AnnotatedClassResolver(config, forType, r).resolveFully();
}
public static AnnotatedClass resolveWithoutSuperTypes(MapperConfig> config, Class> forType) {
return resolveWithoutSuperTypes(config, forType, config);
}
public static AnnotatedClass resolveWithoutSuperTypes(MapperConfig> config, JavaType forType,
MixInResolver r)
{
if (forType.isArrayType() && skippableArray(config, forType.getRawClass())) {
return createArrayType(config, forType.getRawClass());
}
return new AnnotatedClassResolver(config, forType, r).resolveWithoutSuperTypes();
}
public static AnnotatedClass resolveWithoutSuperTypes(MapperConfig> config, Class> forType,
MixInResolver r)
{
if (forType.isArray() && skippableArray(config, forType)) {
return createArrayType(config, forType);
}
return new AnnotatedClassResolver(config, forType, r).resolveWithoutSuperTypes();
}
private static boolean skippableArray(MapperConfig> config, Class> type) {
return (config == null) || (config.findMixInClassFor(type) == null);
}
/**
* Internal helper method used for resolving a small set of "primordial" types for which
* we do not accept any annotation information or overrides.
*/
static AnnotatedClass createPrimordial(Class> raw) {
return new AnnotatedClass(raw);
}
/**
* Internal helper method used for resolving array types, unless they happen
* to have associated mix-in to apply.
*/
static AnnotatedClass createArrayType(MapperConfig> config, Class> raw) {
return new AnnotatedClass(raw);
}
AnnotatedClass resolveFully() {
List superTypes = ClassUtil.findSuperTypes(_type, null, false);
return new AnnotatedClass(_type, _class, superTypes, _primaryMixin,
resolveClassAnnotations(superTypes),
_bindings, _intr, _mixInResolver, _config.getTypeFactory());
}
AnnotatedClass resolveWithoutSuperTypes() {
List superTypes = Collections.emptyList();
return new AnnotatedClass(null, _class, superTypes, _primaryMixin,
resolveClassAnnotations(superTypes),
_bindings, _intr, _config, _config.getTypeFactory());
}
/*
/**********************************************************
/* Class annotation resolution
/**********************************************************
*/
/**
* Initialization method that will recursively collect Jackson
* annotations for this class and all super classes and
* interfaces.
*/
private Annotations resolveClassAnnotations(List superTypes)
{
// Should skip processing if annotation processing disabled
if (_intr == null) {
return NO_ANNOTATIONS;
}
AnnotationCollector resolvedCA = AnnotationCollector.emptyCollector();
// add mix-in annotations first (overrides)
if (_primaryMixin != null) {
resolvedCA = _addClassMixIns(resolvedCA, _class, _primaryMixin);
}
// then annotations from the class itself:
resolvedCA = _addAnnotationsIfNotPresent(resolvedCA,
ClassUtil.findClassAnnotations(_class));
// and then from super types
for (JavaType type : superTypes) {
// and mix mix-in annotations in-between
if (_mixInResolver != null) {
Class> cls = type.getRawClass();
resolvedCA = _addClassMixIns(resolvedCA, cls,
_mixInResolver.findMixInClassFor(cls));
}
resolvedCA = _addAnnotationsIfNotPresent(resolvedCA,
ClassUtil.findClassAnnotations(type.getRawClass()));
}
/* and finally... any annotations there might be for plain
* old Object.class: separate because for all other purposes
* it is just ignored (not included in super types)
*/
// 12-Jul-2009, tatu: Should this be done for interfaces too?
// For now, yes, seems useful for some cases, and not harmful for any?
if (_mixInResolver != null) {
resolvedCA = _addClassMixIns(resolvedCA, Object.class,
_mixInResolver.findMixInClassFor(Object.class));
}
return resolvedCA.asAnnotations();
}
private AnnotationCollector _addClassMixIns(AnnotationCollector annotations,
Class> target, Class> mixin)
{
if (mixin != null) {
// Ok, first: annotations from mix-in class itself:
annotations = _addAnnotationsIfNotPresent(annotations, ClassUtil.findClassAnnotations(mixin));
// And then from its supertypes, if any. But note that we will only consider
// super-types up until reaching the masked class (if found); this because
// often mix-in class is a sub-class (for convenience reasons).
// And if so, we absolutely must NOT include super types of masked class,
// as that would inverse precedence of annotations.
for (Class> parent : ClassUtil.findSuperClasses(mixin, target, false)) {
annotations = _addAnnotationsIfNotPresent(annotations, ClassUtil.findClassAnnotations(parent));
}
}
return annotations;
}
private AnnotationCollector _addAnnotationsIfNotPresent(AnnotationCollector c,
Annotation[] anns)
{
if (anns != null) {
for (Annotation ann : anns) { // first: direct annotations
// note: we will NOT filter out non-Jackson annotations any more
if (!c.isPresent(ann)) {
c = c.addOrOverride(ann);
if (_intr.isAnnotationBundle(ann)) {
c = _addFromBundleIfNotPresent(c, ann);
}
}
}
}
return c;
}
private AnnotationCollector _addFromBundleIfNotPresent(AnnotationCollector c,
Annotation bundle)
{
for (Annotation ann : ClassUtil.findClassAnnotations(bundle.annotationType())) {
// minor optimization: by-pass 2 common JDK meta-annotations
if ((ann instanceof Target) || (ann instanceof Retention)) {
continue;
}
if (!c.isPresent(ann)) {
c = c.addOrOverride(ann);
if (_intr.isAnnotationBundle(ann)) {
c = _addFromBundleIfNotPresent(c, ann);
}
}
}
return c;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy