package com.fasterxml.jackson.failing;

import java.util.*;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.BaseMapTest;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.TypeFactory;

// for [databind#1604]
public class TestTypeFactory1604 extends BaseMapTest
{
    static class Data1604<T> { }

    static class DataList1604<T> extends Data1604<List<T>> {
    }

    static class RefinedDataList1604<T> extends DataList1604<List<T>> {
    }

    public static class SneakyDataList1604<BOGUS,T> extends Data1604<List<T>> {
        
    }

    static class TwoParam1604<KEY,VALUE> { }

    static class SneakyTwoParam1604<V,K> extends TwoParam1604<K,List<V>> { }

    public void testCustomTypesRefinedSimple()
    {
        TypeFactory tf = newTypeFactory();
        JavaType type = tf.constructType(new TypeReference<Data1604<Long>>() { });
        assertEquals(Data1604.class, type.getRawClass());

        JavaType subtype = tf.constructSpecializedType(type, DataList1604.class);
        assertEquals(DataList1604.class, subtype.getRawClass());
        assertEquals(1, subtype.containedTypeCount());

        // should properly resolve type parameter:
        JavaType paramType = subtype.containedType(0);
        assertEquals(Long.class, paramType.getRawClass());
    }

    public void testCustomTypesRefinedNested()
    {
        TypeFactory tf = newTypeFactory();
        JavaType type = tf.constructType(new TypeReference<Data1604<Long>>() { });
        assertEquals(Data1604.class, type.getRawClass());

        JavaType subtype = tf.constructSpecializedType(type, RefinedDataList1604.class);
        assertEquals(RefinedDataList1604.class, subtype.getRawClass());
        assertEquals(1, subtype.containedTypeCount());

        // should properly resolve type parameter:
        JavaType paramType = subtype.containedType(0);
        assertEquals(Long.class, paramType.getRawClass());

        // and have correct parent too
        assertEquals(DataList1604.class, subtype.getSuperClass().getRawClass());
    }

    public void testCustomTypesRefinedSneaky()
    {
        TypeFactory tf = newTypeFactory();
        JavaType type = tf.constructType(new TypeReference<Data1604<Long>>() { });
        assertEquals(Data1604.class, type.getRawClass());

        JavaType subtype = tf.constructSpecializedType(type, SneakyDataList1604.class);
        assertEquals(SneakyDataList1604.class, subtype.getRawClass());
        assertEquals(1, subtype.containedTypeCount());

        // should properly resolve type parameter:
        JavaType paramType = subtype.containedType(0);
        assertEquals(Long.class, paramType.getRawClass());

        // and have correct parent too
        assertEquals(Data1604.class, subtype.getSuperClass().getRawClass());
    }

    public void testTwoParamSneakyCustom()
    {
        TypeFactory tf = newTypeFactory();
        JavaType type = tf.constructType(new TypeReference<TwoParam1604<String,Long>>() { });
        assertEquals(TwoParam1604.class, type.getRawClass());
        assertEquals(String.class, type.containedType(0).getRawClass());
        assertEquals(Long.class, type.containedType(1).getRawClass());

        JavaType subtype = tf.constructSpecializedType(type, SneakyTwoParam1604.class);
        assertEquals(SneakyTwoParam1604.class, subtype.getRawClass());
        assertEquals(TwoParam1604.class, subtype.getSuperClass().getRawClass());
        assertEquals(2, subtype.containedTypeCount());

        // should properly resolve type parameters despite sneaky switching
        JavaType first = subtype.containedType(0);
        assertEquals(List.class, first.getRawClass());
        assertEquals(1, first.containedTypeCount());
        assertEquals(Long.class, first.containedType(0).getRawClass());

        JavaType second = subtype.containedType(1);
        assertEquals(String.class, second.getRawClass());
    }
}

@@ -848,35 +848,35 @@
        JavaType 
-typ
+bas
 e = tf.construct
@@ -899,38 +899,44 @@
 erence%3CData1604%3C
+List%3C
 Long%3E%3E
+%3E
 () %7B %7D);%0A       
@@ -957,36 +957,159 @@
 Data1604.class, 
-type
+base.getRawClass());%0A        assertEquals(1, base.containedTypeCount());%0A        assertEquals(List.class, base.containedType(0)
 .getRawClass());
@@ -1165,19 +1165,19 @@
 zedType(
-typ
+bas
 e, DataL
@@ -1315,60 +1315,8 @@
 ());
-%0A%0A        // should properly resolve type parameter:
 %0A   
@@ -1538,35 +1538,35 @@
        JavaType 
-typ
+bas
 e = tf.construct
@@ -1589,38 +1589,44 @@
 erence%3CData1604%3C
+List%3C
 Long%3E%3E
+%3E
 () %7B %7D);%0A       
@@ -1647,35 +1647,35 @@
 Data1604.class, 
-typ
+bas
 e.getRawClass())
@@ -1732,19 +1732,19 @@
 zedType(
-typ
+bas
 e, Refin
@@ -1863,312 +1863,221 @@
 als(
-1, subtype.containedTypeCount());%0A%0A        // should properly resolve type parameter:%0A        JavaType paramType = subtype.containedType(0);%0A        assertEquals(Long.class, paramType.getRawClass());%0A%0A        // and have correct parent too%0A        assertEquals(DataList1604.class, subtype.getSuperClass()
+DataList1604.class, subtype.getSuperClass().getRawClass());%0A%0A        assertEquals(1, subtype.containedTypeCount());%0A        JavaType paramType = subtype.containedType(0);%0A        assertEquals(Long.class, paramType
 .get
@@ -2201,35 +2201,35 @@
        JavaType 
-typ
+bas
 e = tf.construct
@@ -2260,22 +2260,28 @@
 ata1604%3C
+List%3C
 Long%3E%3E
+%3E
 () %7B %7D);
@@ -2310,35 +2310,35 @@
 Data1604.class, 
-typ
+bas
 e.getRawClass())
@@ -2387,35 +2387,35 @@
 SpecializedType(
-typ
+bas
 e, SneakyDataLis
@@ -2557,60 +2557,8 @@
 ());
-%0A%0A        // should properly resolve type parameter:
 %0A   
@@ -2725,32 +2725,36 @@
 ssertEquals(Data
+List
 1604.class, subt

Fix an issue with new #1604 tests; was not exercising actual problem