HppcContainerDeserializers.java

package com.fasterxml.jackson.datatype.hppc.deser;

import java.io.IOException;
import java.util.*;

import com.fasterxml.jackson.core.*;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.type.LogicalType;
import com.carrotsearch.hppc.*;

public class HppcContainerDeserializers
{
    /**
     * We can either register abstract type defaults via ObjectMapper, or
     * just do it here. For now let's just do it locally; this will allow
     * override of definitions by app code (by using ObjectMapper resolution)
     */
    protected final static HashMap<Class<?>, Class<?>> _concreteMapping =
        new HashMap<Class<?>, Class<?>>();
    static {
        // int:
        _concreteMapping.put(IntContainer.class, IntArrayList.class);
        _concreteMapping.put(IntIndexedContainer.class, IntArrayList.class);
        /* 07-May-2015, tatu: 0.6 -> 0.7 changed names, to drop "Open" part.
         *   Alas, this means that our module can't support pre-0.7 any more
         *   starting with 2.6.
         */
//        _concreteMapping.put(IntSet.class, IntOpenHashSet.class); // for HPPC-0.6
        _concreteMapping.put(IntSet.class, IntHashSet.class);
        _concreteMapping.put(IntDeque.class, IntArrayDeque.class);
    }

    /**
     * Method called to see if this serializer (or a serializer this serializer
     * knows) should be used for given type; if not, null is returned.
     */
    public static JsonDeserializer<?> findDeserializer(DeserializationConfig config,
            final JavaType origType)
        throws JsonMappingException
    {
        JavaType type = origType;
        Class<?> raw = type.getRawClass();

        if (IntContainer.class.isAssignableFrom(raw)) {
            // maybe we have mapping from abstract to concrete type?
            if (type.isAbstract()) {
                Class<?> concrete = _concreteMapping.get(raw);
                if (concrete != null) {
                    // 29-Mar-2016, tatu: was: type.forcedNarrowBy(concrete);
                    type = config.getTypeFactory().constructSpecializedType(type, concrete);
                    raw = concrete;
                }
            }
            
            if (IntIndexedContainer.class.isAssignableFrom(raw)) {
                return new IntIndexedContainerDeserializer(type, config);
            }
            if (IntSet.class.isAssignableFrom(raw)) {
                return new IntSetDeserializer(type, config);
            }
            if (IntDeque.class.isAssignableFrom(raw)) {
                return new IntDequeDeserializer(type, config);
            }
            // how about this? should we signal an error?
            throw JsonMappingException.from((JsonParser)null, "Unrecognized HPPC IntContainer type: "+origType);
        } else if (LongContainer.class.isAssignableFrom(raw)) {
            // !!! TBI
        } else if (FloatContainer.class.isAssignableFrom(raw)) {
            // !!! TBI
        } else if (DoubleContainer.class.isAssignableFrom(raw)) {
            // !!! TBI
        } else if (ByteContainer.class.isAssignableFrom(raw)) {
            // !!! TBI
        } else if (ShortContainer.class.isAssignableFrom(raw)) {
            // !!! TBI
        } else if (CharContainer.class.isAssignableFrom(raw)) {
            // !!! TBI
        }
        return null;
    }        

    // @since 2.11
    public static boolean hasDeserializerFor(DeserializationConfig config,
            final Class<?> rawType) {
        return IntContainer.class.isAssignableFrom(rawType);
    }

    /*
    /**********************************************************************
    /* Intermediate base classes
    /**********************************************************************
     */

    /**
     * Intermediate base class used for various integral (as opposed to
     * floating point) value container types.
     */
    @SuppressWarnings("serial")
    static abstract class IntContainerDeserializerBase<T>
        extends ContainerDeserializerBase<T>
    {
        public IntContainerDeserializerBase(JavaType type, DeserializationConfig config)
        {
            super(type, config);
        }

        @Override // since 2.12
        public LogicalType logicalType() {
            return LogicalType.Collection;
        }

        @Override
        public void deserializeContents(JsonParser p, DeserializationContext ctxt,
                T container)
            throws IOException
        {
            JsonToken t;
            while ((t = p.nextToken()) != JsonToken.END_ARRAY) {
                // whether we should allow truncating conversions?
                int value;
                if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) {
                    // should we catch overflow exceptions?
                    value = p.getIntValue();
                } else {
                    if (t != JsonToken.VALUE_NULL) {
                        ctxt.handleUnexpectedToken(_valueClass, p);
                        return; // never gets here
                    }
                    value = 0;
                }
                add(container, value);
            }
        }

        protected abstract void add(T container, int value);
    }

    /*
    /**********************************************************************
    /* Concrete container implementations; basic integral types
    /**********************************************************************
     */

    // // // int containers
    
    static class IntSetDeserializer extends IntContainerDeserializerBase<IntSet>
    {
        private static final long serialVersionUID = 1L;

        public IntSetDeserializer(JavaType type, DeserializationConfig config)
        {
            super(type, config);
        }

        @Override
        protected void add(IntSet container, int value) {
            container.add(value);
        }
    }

    static class IntIndexedContainerDeserializer extends IntContainerDeserializerBase<IntIndexedContainer>
    {
        private static final long serialVersionUID = 1L;

        public IntIndexedContainerDeserializer(JavaType type, DeserializationConfig config)
        {
            super(type, config);
        }

        @Override
        protected void add(IntIndexedContainer container, int value) {
            container.add(value);
        }
    }
    
    static class IntDequeDeserializer extends IntContainerDeserializerBase<IntDeque>
    {
        private static final long serialVersionUID = 1L;

        public IntDequeDeserializer(JavaType type, DeserializationConfig config)
        {
            super(type, config);
        }

        @Override
        protected void add(IntDeque container, int value) {
            container.addLast(value);
        }
    }

}