package com.fasterxml.jackson.databind.jsontype;

import java.io.Serializable;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.BaseMapTest;
import com.fasterxml.jackson.databind.ObjectMapper;

public class TestScalars extends BaseMapTest
{
    private static class DynamicWrapper {
        @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY)
        public Object value;
        
        @SuppressWarnings("unused")
        public DynamicWrapper() { }
        public DynamicWrapper(Object v) { value = v; }
    }

    static enum TestEnum { A, B; }

    private static class AbstractWrapper {
        @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY)
        public Serializable value;
        
        @SuppressWarnings("unused")
        public AbstractWrapper() { }
        public AbstractWrapper(Serializable v) { value = v; }
    }
    
    /*
    /**********************************************************
    /* Unit tests
    /**********************************************************
     */
    
    /**
     * Ensure that per-property dynamic types work, both for "native" types
     * and others
     */
    public void testScalarsWithTyping() throws Exception
    {
        ObjectMapper m = new ObjectMapper();
        String json;
        DynamicWrapper result;

        // first, check "native" types
        json = m.writeValueAsString(new DynamicWrapper(Integer.valueOf(3)));
        result = m.readValue(json, DynamicWrapper.class);
        assertEquals(Integer.valueOf(3), result.value);

        json = m.writeValueAsString(new DynamicWrapper("abc"));
        result = m.readValue(json, DynamicWrapper.class);
        assertEquals("abc", result.value);

        json = m.writeValueAsString(new DynamicWrapper("abc"));
        result = m.readValue(json, DynamicWrapper.class);
        assertEquals("abc", result.value);

        json = m.writeValueAsString(new DynamicWrapper(Boolean.TRUE));
        result = m.readValue(json, DynamicWrapper.class);
        assertEquals(Boolean.TRUE, result.value);
        
        // then verify other scalars
        json = m.writeValueAsString(new DynamicWrapper(Long.valueOf(7L)));
        result = m.readValue(json, DynamicWrapper.class);
        assertEquals(Long.valueOf(7), result.value);

        json = m.writeValueAsString(new DynamicWrapper(TestEnum.B));
        result = m.readValue(json, DynamicWrapper.class);
        assertEquals(TestEnum.B, result.value);
    }

    public void testScalarsViaAbstractType() throws Exception
    {
        ObjectMapper m = new ObjectMapper();
        String json;
        AbstractWrapper result;

        // first, check "native" types
        json = m.writeValueAsString(new AbstractWrapper(Integer.valueOf(3)));
        result = m.readValue(json, AbstractWrapper.class);
        assertEquals(Integer.valueOf(3), result.value);

        json = m.writeValueAsString(new AbstractWrapper("abc"));
        result = m.readValue(json, AbstractWrapper.class);
        assertEquals("abc", result.value);

        json = m.writeValueAsString(new AbstractWrapper("abc"));
        result = m.readValue(json, AbstractWrapper.class);
        assertEquals("abc", result.value);

        json = m.writeValueAsString(new AbstractWrapper(Boolean.TRUE));
        result = m.readValue(json, AbstractWrapper.class);
        assertEquals(Boolean.TRUE, result.value);
        
        // then verify other scalars
        json = m.writeValueAsString(new AbstractWrapper(Long.valueOf(7L)));
        result = m.readValue(json, AbstractWrapper.class);
        assertEquals(Long.valueOf(7), result.value);

        json = m.writeValueAsString(new AbstractWrapper(TestEnum.B));
        result = m.readValue(json, AbstractWrapper.class);
        assertEquals(TestEnum.B, result.value);
    }
}

@@ -71,16 +71,90 @@
 lizable;
+%0Aimport java.util.ArrayList;%0Aimport java.util.List;%0Aimport java.util.UUID;
 %0A%0Aimport
@@ -995,16 +995,336 @@
  %7D%0A    %7D
+%0A%0A    static class ScalarList %7B%0A        @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY)%0A        public List%3CObject%3E values = new ArrayList%3CObject%3E();%0A%0A        public ScalarList() %7B %7D%0A%0A        public ScalarList add(Object v) %7B%0A            values.add(v);%0A            return this;%0A        %7D%0A    %7D
 %0A    %0A  
@@ -1477,24 +1477,77 @@
 ****%0A     */
+%0A%0A    final ObjectMapper MAPPER = new ObjectMapper();
 %0A    %0A    /*
@@ -1717,53 +1717,8 @@
   %7B%0A
-        ObjectMapper m = new ObjectMapper();%0A
     
@@ -1756,32 +1756,65 @@
 cWrapper result;
+%0A        ObjectMapper m = MAPPER;
 %0A%0A        // fir
@@ -3049,34 +3049,22 @@
 per m = 
-new ObjectMapper()
+MAPPER
 ;%0A      
@@ -4217,32 +4217,32 @@
 Wrapper.class);%0A
-
         assertEq
@@ -4278,11 +4278,762 @@
 );%0A    %7D
+%0A%0A    // Test inspired by %5Bdatabind#1104%5D%0A    public void testHeterogenousStringScalars() throws Exception%0A    %7B%0A        final UUID NULL_UUID = UUID.fromString(%2200000000-0000-0000-0000-000000000000%22);%0A        ScalarList input = new ScalarList()%0A                .add(%22Test%22)%0A                .add(java.lang.Object.class)%0A                .add(NULL_UUID)%0A                ;%0A        String json = MAPPER.writeValueAsString(input);%0A%0A        ScalarList result = MAPPER.readValue(json, ScalarList.class);%0A        assertNotNull(result.values);%0A        assertEquals(3, result.values.size());%0A        assertEquals(%22Test%22, result.values.get(0));%0A        assertEquals(Object.class, result.values.get(1));%0A        assertEquals(NULL_UUID, result.values.get(2));%0A    %7D
 %0A%7D%0A

Add a unit test to outline use case where type id is required wrt #1104.