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

org.codehaus.jackson.map.ext.OptionalHandlerFactory Maven / Gradle / Ivy

Go to download

Data Mapper package is a high-performance data binding package built on Jackson JSON processor

There is a newer version: 1.9.13
Show newest version
package org.codehaus.jackson.map.ext;

import java.util.Collection;
import java.util.Map;

import org.codehaus.jackson.map.*;
import org.codehaus.jackson.map.deser.StdDeserializer;
import org.codehaus.jackson.map.introspect.BasicBeanDescription;
import org.codehaus.jackson.map.util.Provider;
import org.codehaus.jackson.type.JavaType;

/**
 * Helper class used for isolating details of handling optional+external types (Joda datetime,
 * javax.xml classes) from standard factories that offer them.
 * 
 * @author tatu
 *
 * @since 1.6.1
 */
public class OptionalHandlerFactory
{
    /* 1.6.1+ To make 2 main "optional" handler groups (javax.xml.stream, Joda date/time)
     * more dynamic, we better only figure out handlers completely dynamically, if and
     * when they are needed. To do this we need to assume package prefixes.
     */

    private final static String PACKAGE_PREFIX_JODA_DATETIME = "org.joda.time.";
    private final static String PACKAGE_PREFIX_JAVAX_XML = "javax.xml.";

    private final static String SERIALIZERS_FOR_JODA_DATETIME = "org.codehaus.jackson.map.ext.JodaSerializers";
    private final static String SERIALIZERS_FOR_JAVAX_XML = "org.codehaus.jackson.map.ext.CoreXMLSerializers";
    private final static String DESERIALIZERS_FOR_JODA_DATETIME = "org.codehaus.jackson.map.ext.JodaDeserializers";
    private final static String DESERIALIZERS_FOR_JAVAX_XML = "org.codehaus.jackson.map.ext.CoreXMLDeserializers";

    // Plus we also have a single serializer for DOM Node:
    private final static String CLASS_NAME_DOM_NODE = "org.w3c.dom.Node";
    private final static String CLASS_NAME_DOM_DOCUMENT = "org.w3c.dom.Node";
    private final static String SERIALIZER_FOR_DOM_NODE = "org.codehaus.jackson.map.ext.DOMSerializer";
    private final static String DESERIALIZER_FOR_DOM_DOCUMENT = "org.codehaus.jackson.map.ext.DOMDeserializer$DocumentDeserializer";
    private final static String DESERIALIZER_FOR_DOM_NODE = "org.codehaus.jackson.map.ext.DOMDeserializer$NodeDeserializer";
    
    public final static OptionalHandlerFactory instance = new OptionalHandlerFactory();
    
    protected OptionalHandlerFactory() { }

    /*
    /**********************************************************
    /* Public API
    /**********************************************************
     */
    
    public JsonSerializer findSerializer(JavaType type, SerializationConfig config,
            BasicBeanDescription beanInfo)
    {
        Class rawType = type.getRawClass();
        String className = rawType.getName();
        String factoryName;
        
        if (className.startsWith(PACKAGE_PREFIX_JODA_DATETIME)) {
            factoryName = SERIALIZERS_FOR_JODA_DATETIME;
        } else if (className.startsWith(PACKAGE_PREFIX_JAVAX_XML)
                || hasSupertypeStartingWith(rawType, PACKAGE_PREFIX_JAVAX_XML)) {
            factoryName = SERIALIZERS_FOR_JAVAX_XML;
        } else if (doesImplement(rawType, CLASS_NAME_DOM_NODE)) {
            return (JsonSerializer) instantiate(SERIALIZER_FOR_DOM_NODE);
        } else {
            return null;
        }

        Object ob = instantiate(factoryName);
        if (ob == null) { // could warn, if we had logging system (j.u.l?)
            return null;
        }
        @SuppressWarnings("unchecked")
        Provider,JsonSerializer>> prov = (Provider,JsonSerializer>>) ob;
        Collection,JsonSerializer>> entries = prov.provide();

        // first, check for exact match (concrete)
        for (Map.Entry,JsonSerializer> entry : entries) {
            if (rawType == entry.getKey()) {
                return entry.getValue();
            }
        }
        // if no match, check super-type match
        for (Map.Entry,JsonSerializer> entry : entries) {
            if (entry.getKey().isAssignableFrom(rawType)) {
                return entry.getValue();
            }
        }
        // but maybe there's just no match to be found?
        return null;
    }

    public JsonDeserializer findDeserializer(JavaType type, DeserializationConfig config, DeserializerProvider p)
    {
        Class rawType = type.getRawClass();
        String className = rawType.getName();
        String factoryName;
        
        if (className.startsWith(PACKAGE_PREFIX_JODA_DATETIME)) {
            factoryName = DESERIALIZERS_FOR_JODA_DATETIME;
        } else if (className.startsWith(PACKAGE_PREFIX_JAVAX_XML)
                || hasSupertypeStartingWith(rawType, PACKAGE_PREFIX_JAVAX_XML)) {
            factoryName = DESERIALIZERS_FOR_JAVAX_XML;
        } else if (doesImplement(rawType, CLASS_NAME_DOM_DOCUMENT)) {
            return (JsonDeserializer) instantiate(DESERIALIZER_FOR_DOM_DOCUMENT);
        } else if (doesImplement(rawType, CLASS_NAME_DOM_NODE)) {
            return (JsonDeserializer) instantiate(DESERIALIZER_FOR_DOM_NODE);
        } else {
            return null;
        }
        Object ob = instantiate(factoryName);
        if (ob == null) { // could warn, if we had logging system (j.u.l?)
            return null;
        }
        @SuppressWarnings("unchecked")
        Provider> prov = (Provider>) ob;
        Collection> entries = prov.provide();

        // first, check for exact match (concrete)
        for (StdDeserializer deser : entries) {
            if (rawType == deser.getValueClass()) {
                return deser;
            }
        }
        // if no match, check super-type match
        for (StdDeserializer deser : entries) {
            if (deser.getValueClass().isAssignableFrom(rawType)) {
                return deser;
            }
        }
        // but maybe there's just no match to be found?
        return null;
    }
    
    /*
    /**********************************************************
    /* Internal helper methods
    /**********************************************************
     */

    private Object instantiate(String className)
    {
        try {
            return Class.forName(className).newInstance();
        }
        catch (LinkageError e) { }
        // too many different kinds to enumerate here:
        catch (Exception e) { }
        return null;
    }
    
    private boolean doesImplement(Class actualType, String classNameToImplement)
    {
        for (Class type = actualType; type != null; type = type.getSuperclass()) {
            if (type.getName().equals(classNameToImplement)) {
                return true;
            }
            // or maybe one of super-interfaces
            if (hasInterface(type, classNameToImplement)) {
                return true;
            }
        }
        return false;
    }
        
    private boolean hasInterface(Class type, String interfaceToImplement)
    {
        Class[] interfaces = type.getInterfaces();
        for (Class iface : interfaces) {
            if (iface.getName().equals(interfaceToImplement)) {
                return true;
            }
        }
        // maybe super-interface?
        for (Class iface : interfaces) {
            if (hasInterface(iface, interfaceToImplement)) {
                return true;
            }
        }
        return false;
    }

    private boolean hasSupertypeStartingWith(Class rawType, String prefix)
    {
        // first, superclasses
        for (Class supertype = rawType.getSuperclass(); supertype != null; supertype = supertype.getSuperclass()) {
            if (supertype.getName().startsWith(prefix)) {
                return true;
            }
        }
        // then interfaces
        for (Class cls = rawType; cls != null; cls = cls.getSuperclass()) {
            if (hasInterfaceStartingWith(cls, prefix)) {
                return true;
            }
        }
        return false;
    }

    private boolean hasInterfaceStartingWith(Class type, String prefix)
    {
        Class[] interfaces = type.getInterfaces();
        for (Class iface : interfaces) {
            if (iface.getName().startsWith(prefix)) {
                return true;
            }
        }
        // maybe super-interface?
        for (Class iface : interfaces) {
            if (hasInterfaceStartingWith(iface, prefix)) {
                return true;
            }
        }
        return false;
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy