package com.fasterxml.jackson.databind.creators;

import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.introspect.AnnotatedParameter;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;

public class SingleArgCreatorTest extends BaseMapTest
{
    // [databind#430]: single arg BUT named; should not delegate

    static class SingleNamedStringBean {
        final String _ss;

        @JsonCreator
        public SingleNamedStringBean(@JsonProperty("") String ss){
            this._ss = ss;
        }

        public String getSs() { return _ss; }
    }

    // For [databind#614]
    static class SingleNamedButStillDelegating {
        protected final String value;

        @JsonCreator(mode=JsonCreator.Mode.DELEGATING)
        public SingleNamedButStillDelegating(@JsonProperty("foobar") String v){
            value = v;
        }

        public String getFoobar() { return "x"; }
    }
    
    // [databind#557]
    
    static class StringyBean
    {
        public final String value;

        private StringyBean(String value) { this.value = value; }

        public String getValue() {
            return value;
        }
    }

    static class StringyBeanWithProps
    {
        public final String value;

        @JsonCreator
        private StringyBeanWithProps(String v) { value = v; }

        public String getValue() {
            return value;
        }
    }

    @SuppressWarnings("serial")
    static class MyParamIntrospector extends JacksonAnnotationIntrospector
    {
        private final String name;
        
        public MyParamIntrospector(String n) { name = n; }
        
        @Override
        public String findImplicitPropertyName(AnnotatedMember param) {
            if (param instanceof AnnotatedParameter) {
                AnnotatedParameter ap = (AnnotatedParameter) param;
                switch (ap.getIndex()) {
                case 0: return name;
                }
                return "param"+ap.getIndex();
            }
            return super.findImplicitPropertyName(param);
        }
    }

    /*
    /**********************************************************
    /* Test methods
    /**********************************************************
     */

    private final ObjectMapper MAPPER = objectMapper();

    public void testNamedSingleArg() throws Exception
    {
        SingleNamedStringBean bean = MAPPER.readValue(quote("foobar"),
                SingleNamedStringBean.class);
        assertEquals("foobar", bean._ss);
    }

    public void testSingleStringArgWithImplicitName() throws Exception
    {
        final ObjectMapper mapper = new ObjectMapper();
        mapper.setAnnotationIntrospector(new MyParamIntrospector("value"));
        StringyBean bean = mapper.readValue(quote("foobar"), StringyBean.class);
        assertEquals("foobar", bean.getValue());
    }    

    // [databind#714]
    public void testSingleImplicitlyNamedNotDelegating() throws Exception
    {
        final ObjectMapper mapper = new ObjectMapper();
        mapper.setAnnotationIntrospector(new MyParamIntrospector("value"));
        StringyBeanWithProps bean = mapper.readValue("{\"value\":\"x\"}", StringyBeanWithProps.class);
        assertEquals("x", bean.getValue());
    }    
    
    // [databind#714]
    public void testSingleExplicitlyNamedButDelegating() throws Exception
    {
        SingleNamedButStillDelegating bean = MAPPER.readValue(quote("xyz"),
                SingleNamedButStillDelegating.class);
        assertEquals("xyz", bean.value);
    }
}


@@ -2206,24 +2206,968 @@
    %7D%0A    %7D%0A%0A
+    // %5Bdatabind#660%5D%0A    static class ExplicitFactoryBean1 %7B%0A        private String value;%0A%0A        private ExplicitFactoryBean1(String str) %7B%0A            value = null;%0A        %7D%0A%0A        private ExplicitFactoryBean1(String str, boolean b) %7B%0A            value = str;%0A        %7D%0A%0A        @JsonCreator%0A        public ExplicitFactoryBean1 create(String str) %7B%0A            ExplicitFactoryBean1 bean = new ExplicitFactoryBean1(str, false);%0A            bean.value = str;%0A            return bean;%0A        %7D%0A%0A        public String value() %7B return value; %7D%0A    %7D%0A%0A    // %5Bdatabind#660%5D%0A    static class ExplicitFactoryBean2 %7B%0A        private String value;%0A%0A        @JsonCreator%0A        private ExplicitFactoryBean2(String str) %7B%0A            value = null;%0A        %7D%0A%0A        public static ExplicitFactoryBean2 valueOf(String str) %7B%0A            return new ExplicitFactoryBean2(null);%0A        %7D%0A%0A        public String value() %7B return value; %7D%0A    %7D%0A    %0A
     /*%0A    /
@@ -4625,12 +4625,519 @@
 );%0A    %7D
+%0A%0A    public void testExplicitFactory660() throws Exception%0A    %7B%0A        // First, explicit override for factory%0A        ExplicitFactoryBean1 bean = MAPPER.readValue(quote(%22abc%22), ExplicitFactoryBean1.class);%0A        assertNotNull(bean);%0A        assertEquals(%22abc%22, bean.value());%0A%0A        // and then one for private constructor%0A        ExplicitFactoryBean2 bean2 = MAPPER.readValue(quote(%22def%22), ExplicitFactoryBean2.class);%0A        assertNotNull(bean2);%0A        assertEquals(%22def%22, bean2.value());%0A    %7D
 %0A%7D%0A%0A

Add a (failing) test for #660