package com.fasterxml.jackson.databind.ser.std;

import java.io.IOException;
import java.util.Calendar;
import java.util.Date;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;

@SuppressWarnings("serial")
public class StdKeySerializers
{
    protected final static JsonSerializer<Object> DEFAULT_KEY_SERIALIZER = new StdKeySerializer();

    protected final static JsonSerializer<Object> DEFAULT_STRING_SERIALIZER = new StringKeySerializer();

    private StdKeySerializers() { }

    /**
     * @param config Serialization configuration in use, may be needed in choosing
     *    serializer to use
     * @param rawKeyType Type of key values to serialize
     * @param useDefault If no match is found, should we return fallback deserializer
     *    (true), or null (false)?
     */
    public static JsonSerializer<Object> getStdKeySerializer(SerializationConfig config,
            Class<?> rawKeyType, boolean useDefault)
    {
        // 24-Sep-2015, tatu: Important -- should ONLY consider types for which `@JsonValue`
        //    can not be used, since caller has not yet checked for that annotation
        //    This is why Enum types are not handled here quite yet

        if (rawKeyType != null) {
            if (rawKeyType == String.class) {
                return DEFAULT_STRING_SERIALIZER;
            }
            if (rawKeyType == Object.class || rawKeyType.isPrimitive()
                    || Number.class.isAssignableFrom(rawKeyType)) {
                return DEFAULT_KEY_SERIALIZER;
            }
            if (rawKeyType == Class.class) {
                return new Default(Default.TYPE_CLASS, rawKeyType);
            }
            if (Date.class.isAssignableFrom(rawKeyType)) {
                return new Default(Default.TYPE_DATE, rawKeyType);
            }
            if (Calendar.class.isAssignableFrom(rawKeyType)) {
                return new Default(Default.TYPE_CALENDAR, rawKeyType);
            }
            // other JDK types we know convert properly with 'toString()'?
            if (rawKeyType == java.util.UUID.class) {
                return new Default(Default.TYPE_TO_STRING, rawKeyType);
            }

        }
        return useDefault ? DEFAULT_KEY_SERIALIZER : null;
    }

    /**
     * Method called if no specified key serializer was located; will return a
     * "default" key serializer.
     *
     * @since 2.7
     */
    public static JsonSerializer<Object> getFallbackKeySerializer(SerializationConfig config,
            Class<?> rawKeyType) {
        if (rawKeyType != null) {
            if (rawKeyType.isEnum()) {
                return new Default(Default.TYPE_ENUM, rawKeyType);
            }
        }
        return DEFAULT_KEY_SERIALIZER;
    }
    
    /**
     * @deprecated Since 2.5
     */
    @Deprecated
    public static JsonSerializer<Object> getStdKeySerializer(JavaType keyType) {
        return getStdKeySerializer(null, keyType.getRawClass(), true);
    }

    /**
     * @deprecated since 2.7
     */
    public static JsonSerializer<Object> getDefault() {
        return DEFAULT_KEY_SERIALIZER;
    }

    /*
    /**********************************************************
    /* Standard implementations used
    /**********************************************************
     */

    public static class Default extends StdSerializer<Object> {
        final static int TYPE_DATE = 1;
        final static int TYPE_CALENDAR = 2;
        final static int TYPE_CLASS = 3;
        final static int TYPE_ENUM = 4;
        final static int TYPE_TO_STRING = 5;

        protected final int _typeId;
        
        public Default(int typeId, Class<?> type) {
            super(type, false);
            _typeId = typeId;
        }

        @Override
        public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException {
            switch (_typeId) {
            case TYPE_DATE:
                provider.defaultSerializeDateKey((Date)value, g);
                break;
            case TYPE_CALENDAR:
                provider.defaultSerializeDateKey(((Calendar) value).getTimeInMillis(), g);
                break;
            case TYPE_CLASS:
                g.writeFieldName(((Class<?>)value).getName());
                break;
            case TYPE_ENUM:
                {
                    String str = provider.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
                            ? value.toString() : ((Enum<?>) value).name();
                    g.writeFieldName(str);
                }
                break;
            case TYPE_TO_STRING:
            default:
                g.writeFieldName(value.toString());
            }
        }
    }

    public static class StringKeySerializer extends StdSerializer<Object>
    {
        public StringKeySerializer() { super(String.class, false); }

        @Override
        public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException {
            g.writeFieldName((String) value);
        }
    }

    /*
    /**********************************************************
    /* Deprecated implementations: to be removed in future
    /**********************************************************
     */

    @Deprecated // since 2.6; remove from 2.7 or later
    public static class DateKeySerializer extends StdSerializer<Date> {
        protected final static JsonSerializer<?> instance = new DateKeySerializer();

        public DateKeySerializer() { super(Date.class); }
        
        @Override
        public void serialize(Date value, JsonGenerator g, SerializerProvider provider) throws IOException {
            provider.defaultSerializeDateKey(value, g);
        }
    }

    @Deprecated // since 2.6; remove from 2.7 or later
    public static class CalendarKeySerializer extends StdSerializer<Calendar> {
        protected final static JsonSerializer<?> instance = new CalendarKeySerializer();

        public CalendarKeySerializer() { super(Calendar.class); }

        @Override
        public void serialize(Calendar value, JsonGenerator g, SerializerProvider provider) throws IOException {
            provider.defaultSerializeDateKey(value.getTimeInMillis(), g);
        }
    }
}

@@ -2745,20 +2745,16 @@
 ;%0A    %7D%0A
-    
 %0A    /**
@@ -2777,17 +2777,17 @@
 ted 
-S
+s
 ince 2.
-5
+7
 %0A   
@@ -2811,212 +2811,8 @@
 ted%0A
-    public static JsonSerializer%3CObject%3E getStdKeySerializer(JavaType keyType) %7B%0A        return getStdKeySerializer(null, keyType.getRawClass(), true);%0A    %7D%0A%0A    /**%0A     * @deprecated since 2.7%0A     */%0A
     
@@ -4862,1204 +4862,7 @@
    %7D
-%0A%0A    /*%0A    /**********************************************************%0A    /* Deprecated implementations: to be removed in future%0A    /**********************************************************%0A     */%0A%0A    @Deprecated // since 2.6; remove from 2.7 or later%0A    public static class DateKeySerializer extends StdSerializer%3CDate%3E %7B%0A        protected final static JsonSerializer%3C?%3E instance = new DateKeySerializer();%0A%0A        public DateKeySerializer() %7B super(Date.class); %7D%0A        %0A        @Override%0A        public void serialize(Date value, JsonGenerator g, SerializerProvider provider) throws IOException %7B%0A            provider.defaultSerializeDateKey(value, g);%0A        %7D%0A    %7D%0A%0A    @Deprecated // since 2.6; remove from 2.7 or later%0A    public static class CalendarKeySerializer extends StdSerializer%3CCalendar%3E %7B%0A        protected final static JsonSerializer%3C?%3E instance = new CalendarKeySerializer();%0A%0A        public CalendarKeySerializer() %7B super(Calendar.class); %7D%0A%0A        @Override%0A        public void serialize(Calendar value, JsonGenerator g, SerializerProvider provider) throws IOException %7B%0A            provider.defaultSerializeDateKey(value.getTimeInMillis(), g);%0A        %7D%0A    %7D
 %0A%7D%0A

Remove w deprecated internal implentation classes (not used since 2.5)