Jackson Annotations Source Code

Jackson is "the Java JSON library" or "the best JSON parser for Java". Or simply as "JSON for Java".

Jackson Annotations Source Code files are provided in the source packge (jackson-annotations-2.12.4-sources.jar). You can download it at Jackson Maven Website.

You can also browse Jackson Annotations Source Code below:

✍: FYIcenter.com

com/fasterxml/jackson/databind/introspect/AnnotatedClassResolver.java

package com.fasterxml.jackson.databind.introspect;

import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

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 static Class<?> CLS_OBJECT = Object.class;
    private final static Class<?> CLS_ENUM = Enum.class;

    private final static Class<?> CLS_LIST = List.class;
    private final static Class<?> CLS_MAP = Map.class;
    
    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;

    /**
     * @since 2.11
     */
    private final boolean _collectAnnotations;

    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 = (r == null) ? null : r.findMixInClassFor(_class);

        // Also... JDK types do not have annotations that are of interest to us
        // At least JDK container types
        _collectAnnotations = (_intr != null) &&
                (!ClassUtil.isJDKClass(_class) || !_type.isContainerType());
    }

    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 = (r == null) ? null : r.findMixInClassFor(_class);
        }

        _collectAnnotations = (_intr != null);
    }

    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<JavaType> superTypes = new ArrayList<JavaType>(8);
        if (!_type.hasRawClass(Object.class)) {
            if (_type.isInterface()) {
                _addSuperInterfaces(_type, superTypes, false);
            } else {
                _addSuperTypes(_type, superTypes, false);
            }
        }
//System.err.println("resolveFully("+_type.getRawClass().getSimpleName()+") ("+superTypes.size()+") -> "+superTypes);
        return new AnnotatedClass(_type, _class, superTypes, _primaryMixin,
                resolveClassAnnotations(superTypes),
                _bindings, _intr, _mixInResolver, _config.getTypeFactory(),
                _collectAnnotations);

    }

    AnnotatedClass resolveWithoutSuperTypes() {
        List<JavaType> superTypes = Collections.<JavaType>emptyList();
        return new AnnotatedClass(null, _class, superTypes, _primaryMixin,
                resolveClassAnnotations(superTypes),
                _bindings, _intr, _mixInResolver, _config.getTypeFactory(),
                _collectAnnotations);
    }

    private static void _addSuperTypes(JavaType type, List<JavaType> result,
            boolean addClassItself)
    {
        final Class<?> cls = type.getRawClass();
        // 15-Oct-2019, tatu: certain paths do not lead to useful information, so prune
        //    as optimization
        if ((cls == CLS_OBJECT) || (cls == CLS_ENUM)) {
            return;
        }
        if (addClassItself) {
            if (_contains(result, cls)) { // already added, no need to check supers
                return;
            }
            result.add(type);
        }
        for (JavaType intCls : type.getInterfaces()) {
            _addSuperInterfaces(intCls, result, true);
        }
        final JavaType superType = type.getSuperClass();
        if (superType != null) {
            _addSuperTypes(superType, result, true);
        }
    }

    private static void _addSuperInterfaces(JavaType type, List<JavaType> result,
            boolean addClassItself)
    {
        final Class<?> cls = type.getRawClass();
        if (addClassItself) {
            if (_contains(result, cls)) { // already added, no need to check supers
                return;
            }
            result.add(type);
            // 30-Oct-2019, tatu: Further, no point going beyond some containers
            if ((cls == CLS_LIST) || (cls == CLS_MAP)) {
                return;
            }
        }
        for (JavaType intCls : type.getInterfaces()) {
            _addSuperInterfaces(intCls, result, true);
        }
    }

    private static boolean _contains(List<JavaType> found, Class<?> raw) {
        for (int i = 0, end = found.size(); i < end; ++i) {
            if (found.get(i).getRawClass() == raw) {
                return true;
            }
        }
        return false;
    }
    
    /*
    /**********************************************************
    /* Class annotation resolution
    /**********************************************************
     */

    /**
     * Initialization method that will recursively collect Jackson
     * annotations for this class and all super classes and
     * interfaces.
     */
    private Annotations resolveClassAnnotations(List<JavaType> superTypes)
    {
        // Should skip processing if annotation processing disabled
        if (_intr == null) {
            return NO_ANNOTATIONS;
        }
        // Plus we may or may not have mix-ins to consider
        final boolean checkMixIns = (_mixInResolver != null)
                && (!(_mixInResolver instanceof SimpleMixInResolver)
                        || ((SimpleMixInResolver) _mixInResolver).hasMixIns());

        // also skip if there's nothing to do
        if (!checkMixIns && !_collectAnnotations) {
            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:
        // 06-Oct-2019, tatu: [databind#2464] Skip class annotations for JDK classes
        if (_collectAnnotations) {
            resolvedCA = _addAnnotationsIfNotPresent(resolvedCA,
                    ClassUtil.findClassAnnotations(_class));
        }

        // and then from super types
        for (JavaType type : superTypes) {
            // and mix mix-in annotations in-between
            if (checkMixIns) {
                Class<?> cls = type.getRawClass();
                resolvedCA = _addClassMixIns(resolvedCA, cls,
                        _mixInResolver.findMixInClassFor(cls));
            }
            if (_collectAnnotations) {
                resolvedCA = _addAnnotationsIfNotPresent(resolvedCA,
                        ClassUtil.findClassAnnotations(type.getRawClass()));
            }
        }

        // and finally... any annotations there might be for plain old Object.class:
        // separate because otherwise 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 (checkMixIns) {
            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;
    }
}

com/fasterxml/jackson/databind/introspect/AnnotatedClassResolver.java

 

⇒ Jackson Dataformat Extensions

⇐ Jackson Data Binding Source Code

⇑ Downloading and Reviewing jackson-*.jar

⇑⇑ Jackson - Java JSON library

2022-02-19, 36615👍, 0💬