package com.fasterxml.jackson.databind.convert;

import java.math.BigDecimal;
import java.math.BigInteger;

import java.util.*;

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

/**
 * Tests to verify implementation of [databind#540]; also for
 * follow up work of:
 *
 * - [databind#994]
 */
public class EmptyArrayAsNullTest extends BaseMapTest
{
    private final ObjectMapper MAPPER = new ObjectMapper();
    private final ObjectReader DEFAULT_READER = MAPPER.reader();
    private final ObjectReader READER_WITH_ARRAYS = DEFAULT_READER
            .with(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);

    static class Bean {
        public String a = "foo";
    }

    final static String EMPTY_ARRAY = "  [\n]";

    /*
    /**********************************************************
    /* Test methods, settings
    /**********************************************************
     */

    public void testSettings() {
        assertFalse(MAPPER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT));
        assertFalse(DEFAULT_READER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT));
        assertTrue(READER_WITH_ARRAYS.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT));
    }

    /*
    /**********************************************************
    /* Test methods, POJOs
    /**********************************************************
     */

    // [databind#540]
    public void testPOJOFromEmptyArray() throws Exception
    {
        // first, verify default settings which do not accept empty Array
        try {
            DEFAULT_READER.forType(Bean.class)
                .readValue(EMPTY_ARRAY);
            fail("Should not accept Empty Array for POJO by default");
        } catch (JsonMappingException e) {
            verifyException(e, "from Array value (token `JsonToken.START_ARRAY`)");
            assertValidLocation(e.getLocation());
        }

        // should be ok to enable dynamically:
        Bean result = READER_WITH_ARRAYS.forType(Bean.class)
                .readValue(EMPTY_ARRAY);
        assertNull(result);
    }

    /*
    /**********************************************************
    /* Test methods, Maps
    /**********************************************************
     */

    public void testMapFromEmptyArray() throws Exception
    {
        // first, verify default settings which do not accept empty Array
        try {
            DEFAULT_READER.forType(Map.class)
                .readValue(EMPTY_ARRAY);
            fail("Should not accept Empty Array for Map by default");
        } catch (JsonMappingException e) {
            verifyException(e, "from Array value (token `JsonToken.START_ARRAY`)");
        }
        // should be ok to enable dynamically:
        Map<?,?> result = READER_WITH_ARRAYS.forType(Map.class)
                .readValue(EMPTY_ARRAY);
        assertNull(result);
    }

    public void testEnumMapFromEmptyArray() throws Exception
    {
    
        EnumMap<?,?> result2 = READER_WITH_ARRAYS.forType(new TypeReference<EnumMap<ABC,String>>() { })
                .readValue(EMPTY_ARRAY);
        assertNull(result2);
    }

    /*
    /**********************************************************
    /* Test methods, primitives/wrappers
    /**********************************************************
     */

    public void testWrapperFromEmptyArray() throws Exception
    {
        _testNullWrapper(Boolean.class);
        _testNullWrapper(Byte.class);
        _testNullWrapper(Character.class);
        _testNullWrapper(Short.class);
        _testNullWrapper(Integer.class);
        _testNullWrapper(Long.class);
        _testNullWrapper(Float.class);
        _testNullWrapper(Double.class);
    }

    /*
    /**********************************************************
    /* Test methods, other
    /**********************************************************
     */

    public void testNullStringFromEmptyArray() throws Exception {
        _testNullWrapper(String.class);
    }

    public void testNullEnumFromEmptyArray() throws Exception {
        _testNullWrapper(ABC.class);
    }

    public void testStdJdkTypesFromEmptyArray() throws Exception
    {
        _testNullWrapper(BigInteger.class);
        _testNullWrapper(BigDecimal.class);

        _testNullWrapper(UUID.class);

        _testNullWrapper(Date.class);
        _testNullWrapper(Calendar.class);
    }

    /*
    /**********************************************************
    /* Helper methods
    /**********************************************************
     */
    
    private void _testNullWrapper(Class<?> cls) throws Exception
    {
        Object result = READER_WITH_ARRAYS.forType(cls).readValue(EMPTY_ARRAY);
        assertNull(result);
    }
}

@@ -216,16 +216,84 @@
 abind.*;
+%0Aimport com.fasterxml.jackson.databind.exc.MismatchedInputException;
 %0A%0A/**%0A *
@@ -501,18 +501,14 @@
 R = 
-new Object
+shared
 Mapp
@@ -1583,32 +1583,38 @@
 JOFromEmptyArray
+Legacy
 () throws Except
@@ -2561,307 +2561,45 @@
     
-try %7B%0A            DEFAULT_READER.forType(Map.class)%0A                .readValue(EMPTY_ARRAY);%0A            fail(%22Should not accept 
+_verifyFailFor
 Empty
- 
 Array
- for Map by default%22);%0A        %7D catch (JsonMappingException e) %7B%0A            verifyException(e, %22from Array value (token %60JsonToken.START_ARRAY%60)%22);%0A        %7D
+(Map.class);%0A
 %0A   
@@ -2774,32 +2774,33 @@
 result);%0A    %7D%0A%0A
+%0A
     public void 
@@ -4158,32 +4158,72 @@
 ecimal.class);%0A%0A
+        _testNullWrapper(String.class);%0A
         _testNul
@@ -4645,32 +4645,32 @@
 e(EMPTY_ARRAY);%0A
-
         assertNu
@@ -4686,11 +4686,438 @@
 );%0A    %7D
+%0A%0A    private void _verifyFailForEmptyArray(Class%3C?%3E targetType) throws Exception%0A    %7B%0A        try %7B%0A            DEFAULT_READER.forType(targetType)%0A                .readValue(EMPTY_ARRAY);%0A            fail(%22Should not accept Empty Array for %22+targetType.getName()+%22 by default%22);%0A        %7D catch (MismatchedInputException e) %7B%0A            verifyException(e, %22from Array value (token %60JsonToken.START_ARRAY%60)%22);%0A        %7D%0A    %7D
 %0A%7D%0A

test refactoring