All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fasterxml.jackson.databind.jsontype.impl.TypeNameIdResolver Maven / Gradle / Ivy

Go to download

General data-binding functionality for Jackson: works on core streaming API

There is a newer version: 2.17.0
Show newest version
package com.fasterxml.jackson.databind.jsontype.impl;

import java.util.*;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DatabindContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.jsontype.NamedType;

public class TypeNameIdResolver extends TypeIdResolverBase
{
    protected final MapperConfig _config;
    
    /**
     * Mappings from class name to type id, used for serialization
     */
    protected final Map _typeToId;

    /**
     * Mappings from type id to JavaType, used for deserialization
     */
    protected final Map _idToType;
    
    protected TypeNameIdResolver(MapperConfig config, JavaType baseType,
            Map typeToId, Map idToType)
    {
        super(baseType, config.getTypeFactory());
        _config = config;
        _typeToId = typeToId;
        _idToType = idToType;
    }
 
    public static TypeNameIdResolver construct(MapperConfig config, JavaType baseType,
            Collection subtypes, boolean forSer, boolean forDeser)
    {
        // sanity check
        if (forSer == forDeser) throw new IllegalArgumentException();
        Map typeToId = null;
        Map idToType = null;

        if (forSer) {
            typeToId = new HashMap();
        }
        if (forDeser) {
            idToType = new HashMap();
            // 14-Apr-2016, tatu: Apparently needed for special case of `defaultImpl`;
            //    see [databind#1198] for details.
            typeToId = new TreeMap();
        }
        if (subtypes != null) {
            for (NamedType t : subtypes) {
                /* no name? Need to figure out default; for now, let's just
                 * use non-qualified class name
                 */
                Class cls = t.getType();
                String id = t.hasName() ? t.getName() : _defaultTypeId(cls);
                if (forSer) {
                    typeToId.put(cls.getName(), id);
                }
                if (forDeser) {
                    // One more problem; sometimes we have same name for multiple types;
                    // if so, use most specific
                    JavaType prev = idToType.get(id);
                    if (prev != null) { // Can only override if more specific
                        if (cls.isAssignableFrom(prev.getRawClass())) { // nope, more generic (or same)
                            continue;
                        }
                    }
                    idToType.put(id, config.constructType(cls));
                }
            }
        }
        return new TypeNameIdResolver(config, baseType, typeToId, idToType);
    }

    @Override
    public JsonTypeInfo.Id getMechanism() { return JsonTypeInfo.Id.NAME; }

    @Override
    public String idFromValue(Object value)
    {
        return idFromClass(value.getClass());
    }

    protected String idFromClass(Class clazz)
    {
        if (clazz == null) {
            return null;
        }
        Class cls = _typeFactory.constructType(clazz).getRawClass();
        final String key = cls.getName();
        String name;

        synchronized (_typeToId) {
            name = _typeToId.get(key);
            if (name == null) {
                // 24-Feb-2011, tatu: As per [JACKSON-498], may need to dynamically look up name
                // can either throw an exception, or use default name...
                if (_config.isAnnotationProcessingEnabled()) {
                    BeanDescription beanDesc = _config.introspectClassAnnotations(cls);
                    name = _config.getAnnotationIntrospector().findTypeName(beanDesc.getClassInfo());
                }
                if (name == null) {
                    // And if still not found, let's choose default?
                    name = _defaultTypeId(cls);
                }
                _typeToId.put(key, name);
            }
        }
        return name;
    }

    @Override
    public String idFromValueAndType(Object value, Class type) {
        /* 18-Jan-2013, tatu: We may be called with null value occasionally
         *   it seems; nothing much we can figure out that way.
         */
        if (value == null) {
            return idFromClass(type);
        }
        return idFromValue(value);
    }

    @Deprecated
    @Override
    public JavaType typeFromId(String id) {
        return _typeFromId(id);
    }    

    @Override
    public JavaType typeFromId(DatabindContext context, String id) {
        return _typeFromId(id);
    }
    
    protected JavaType _typeFromId(String id) {
        /* Now: if no type is found, should we try to locate it by
         * some other means? (specifically, if in same package as base type,
         * could just try Class.forName)
         * For now let's not add any such workarounds; can add if need be
         */
        return _idToType.get(id);
    }    

    @Override
    public String getDescForKnownTypeIds() {
        return new TreeSet(_idToType.keySet()).toString();
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append('[').append(getClass().getName());
        sb.append("; id-to-type=").append(_idToType);
        sb.append(']');
        return sb.toString();
    }
    
    /*
    /*********************************************************
    /* Helper methods
    /*********************************************************
     */
    
    /**
     * If no name was explicitly given for a class, we will just
     * use non-qualified class name
     */
    protected static String _defaultTypeId(Class cls)
    {
        String n = cls.getName();
        int ix = n.lastIndexOf('.');
        return (ix < 0) ? n : n.substring(ix+1);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy