com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver.java Source code

Java tutorial

Introduction

Here is the source code for com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver.java

Source

package com.fasterxml.jackson.databind.module;

import java.lang.reflect.Modifier;
import java.util.*;

import com.fasterxml.jackson.databind.AbstractTypeResolver;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.ClassKey;

/**
 * Simple {@link AbstractTypeResolver} implementation, which is
 * based on static mapping from abstract super types into
 * sub types (concrete or abstract), but retaining generic
 * parameterization.
 * Can be used for things like specifying which implementation of
 * {@link java.util.Collection} to use:
 *<pre>
 *  SimpleAbstractTypeResolver resolver = new SimpleAbstractTypeResolver();
 *  // To make all properties declared as Collection, List, to LinkedList
 *  resolver.addMapping(Collection.class, LinkedList.class);
 *  resolver.addMapping(List.class, LinkedList.class);
 *</pre>
 * Can also be used as an alternative to per-class annotations when defining
 * concrete implementations; however, only works with abstract types (since
 * this is only called for abstract types)
 */
public class SimpleAbstractTypeResolver extends AbstractTypeResolver implements java.io.Serializable {
    private static final long serialVersionUID = 8635483102371490919L;

    /**
     * Mappings from super types to subtypes
     */
    protected final HashMap<ClassKey, Class<?>> _mappings = new HashMap<ClassKey, Class<?>>();

    /**
     * Method for adding a mapping from super type to specific subtype.
     * Arguments will be checked by method, to ensure that <code>superType</code>
     * is abstract (since resolver is never called for concrete classes);
     * as well as to ensure that there is supertype/subtype relationship
     * (to ensure there won't be cycles during resolution).
     * 
     * @param superType Abstract type to resolve
     * @param subType Sub-class of superType, to map superTo to
     * 
     * @return This resolver, to allow chaining of initializations
     */
    public <T> SimpleAbstractTypeResolver addMapping(Class<T> superType, Class<? extends T> subType) {
        // Sanity checks, just in case someone tries to force typing...
        if (superType == subType) {
            throw new IllegalArgumentException("Can not add mapping from class to itself");
        }
        if (!superType.isAssignableFrom(subType)) {
            throw new IllegalArgumentException("Can not add mapping from class " + superType.getName() + " to "
                    + subType.getName() + ", as latter is not a subtype of former");
        }
        if (!Modifier.isAbstract(superType.getModifiers())) {
            throw new IllegalArgumentException(
                    "Can not add mapping from class " + superType.getName() + " since it is not abstract");
        }
        _mappings.put(new ClassKey(superType), subType);
        return this;
    }

    @Override
    public JavaType findTypeMapping(DeserializationConfig config, JavaType type) {
        // this is the main mapping base, so let's 
        Class<?> src = type.getRawClass();
        Class<?> dst = _mappings.get(new ClassKey(src));
        if (dst == null) {
            return null;
        }
        return type.narrowBy(dst);
    }

    @Override
    public JavaType resolveAbstractType(DeserializationConfig config, JavaType type) {
        // never materialize anything, so:
        return null;
    }
}