Fix [JACKSON-700]

diff --git a/release-notes/CREDITS b/release-notes/CREDITS
index 5be9249..f518c77 100644
--- a/release-notes/CREDITS
+++ b/release-notes/CREDITS
@@ -620,7 +620,7 @@
   * [JACKSON-508] Type information lost when serializing List<List<X>>
    [1.7.4]
 
-Pascal GŽlinas:
+Pascal GŽlinas:
   * Suggested [JACKSON-541] with patch: Remove the need for @JsonCreator on
     multi-arg constructor iff all parameters have @JsonProperty
    [1.7.5]
@@ -782,3 +782,8 @@
   * Suggested [JACKSON-650] Allow dealing with missing filter ids, by adding
     'SimpleFilterProvider.setFailOnUnknownId()' to specify if exception is thrown or not.
    [1.9.0]
+
+Ben Hale:
+  * Reported [JACKSON-700] Type problems with properties that have different
+    types for constructor property, setter and/or field
+   [1.9.1]
diff --git a/release-notes/VERSION b/release-notes/VERSION
index 446e10d..9a85901 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -7,6 +7,10 @@
   The second patch release for 1.9.
   
   Fixes:
+
+  * [JACKSON-700] Type problems with properties that have different types
+    for constructor property, setter and/or field
+   (reported by Ben H)
   
 ------------------------------------------------------------------------
 === History: ===
diff --git a/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerBuilder.java b/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerBuilder.java
index 505aa68..5c1030d 100644
--- a/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerBuilder.java
+++ b/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerBuilder.java
@@ -81,7 +81,7 @@
     
     /*
     /**********************************************************
-    /* Construction and setters
+    /* Life-cycle: construction
     /**********************************************************
      */
     
@@ -118,6 +118,12 @@
         return new HashMap<String, SettableBeanProperty>(src);
     }
     
+    /*
+    /**********************************************************
+    /* Life-cycle: state modification (adders, setters)
+    /**********************************************************
+     */
+
     /**
      * Method for adding a new property or replacing a property.
      */
@@ -157,6 +163,20 @@
     }
 
     /**
+     * @since 1.9
+     */
+    public void addInjectable(String propertyName, JavaType propertyType,
+            Annotations contextAnnotations, AnnotatedMember member,
+            Object valueId)
+    {
+        if (_injectables == null) {
+            _injectables = new ArrayList<ValueInjector>();
+        }
+        _injectables.add(new ValueInjector(propertyName, propertyType,
+                contextAnnotations, member, valueId));
+    }
+    
+    /**
      * Method that will add property name as one of properties that can
      * be ignored if not recognized.
      */
@@ -169,6 +189,48 @@
     }
 
     /**
+     * Method called by deserializer factory, when a "creator property"
+     * (something that is passed via constructor- or factory method argument;
+     * instead of setter or field).
+     *<p>
+     * Default implementation does not do anything; we may need to revisit this
+     * decision if these properties need to be available through accessors.
+     * For now, however, we just have to ensure that we don't try to resolve
+     * types that masked setter/field has (see [JACKSON-700] for details).
+     * 
+     * @since 1.9.2
+     */
+    public void addCreatorProperty(BeanPropertyDefinition propDef)
+    {
+        // do nothing
+    }
+    
+    public void setAnySetter(SettableAnyProperty s)
+    {
+        if (_anySetter != null && s != null) {
+            throw new IllegalStateException("_anySetter already set to non-null");
+        }
+        _anySetter = s;
+    }
+
+    public void setIgnoreUnknownProperties(boolean ignore) {
+        _ignoreAllUnknown = ignore;
+    }
+
+    /**
+     * @since 1.9
+     */
+    public void setValueInstantiator(ValueInstantiator inst) {
+        _valueInstantiator = inst;
+    }
+    
+    /*
+    /**********************************************************
+    /* Public accessors
+    /**********************************************************
+     */
+    
+    /**
      * Method that allows accessing all properties that this
      * builder currently contains.
      *<p>
@@ -191,45 +253,12 @@
         return _properties.remove(name);
     }
 
-    public void setAnySetter(SettableAnyProperty s)
-    {
-        if (_anySetter != null && s != null) {
-            throw new IllegalStateException("_anySetter already set to non-null");
-        }
-        _anySetter = s;
-    }
-
-    public void setIgnoreUnknownProperties(boolean ignore) {
-        _ignoreAllUnknown = ignore;
-    }
-
-    /**
-     * @since 1.9
-     */
-    public void setValueInstantiator(ValueInstantiator inst) {
-        _valueInstantiator = inst;
-    }
-
     /**
      * @since 1.9
      */
     public ValueInstantiator getValueInstantiator() {
         return _valueInstantiator;
     }
-
-    /**
-     * @since 1.9
-     */
-    public void addInjectable(String propertyName, JavaType propertyType,
-            Annotations contextAnnotations, AnnotatedMember member,
-            Object valueId)
-    {
-        if (_injectables == null) {
-            _injectables = new ArrayList<ValueInjector>();
-        }
-        _injectables.add(new ValueInjector(propertyName, propertyType,
-                contextAnnotations, member, valueId));
-    }
     
     /*
     /**********************************************************
diff --git a/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerFactory.java b/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerFactory.java
index 9bb39ed..36d6207 100644
--- a/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerFactory.java
+++ b/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerFactory.java
@@ -1051,7 +1051,16 @@
             if (ignored.contains(name)) { // explicit ignoral using @JsonIgnoreProperties needs to block entries
                 continue;
             }
-            // primary: have a getter?
+            /* [JACKSON-700] If property as passed via constructor parameter, we must
+             *   handle things in special way. Not sure what is the most optimal way...
+             *   for now, let's just call a (new) method in builder, which does nothing.
+             */
+            if (property.hasConstructorParameter()) {
+                // but let's call a method just to allow custom builders to be aware...
+                builder.addCreatorProperty(property);
+                continue;
+            }
+            // primary: have a setter?
             if (property.hasSetter()) {
                 AnnotatedMethod setter = property.getSetter();
                 // [JACKSON-429] Some types are declared as ignorable as well
diff --git a/src/test/org/codehaus/jackson/map/deser/TestCreators2.java b/src/test/org/codehaus/jackson/map/deser/TestCreators2.java
index 92a6f5c..9eda865 100644
--- a/src/test/org/codehaus/jackson/map/deser/TestCreators2.java
+++ b/src/test/org/codehaus/jackson/map/deser/TestCreators2.java
@@ -167,6 +167,18 @@
         }
     }
     
+    static interface Issue700Set extends java.util.Set<Object> { }
+
+    static class Issue700Bean
+    {
+        protected Issue700Set item;
+
+        @JsonCreator
+        public Issue700Bean(@JsonProperty("item") String item) { }
+
+        public String getItem() { return null; }
+    }
+    
     /*
     /**********************************************************
     /* Unit tests
@@ -318,4 +330,12 @@
         bb = m.readValue(quote("true"), BooleanBean.class);
         assertEquals(Boolean.TRUE, bb.value);
     }
+
+    // [JACKSON-700]
+    public void testCreatorProperties() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        Issue700Bean value = mapper.readValue("{ \"item\" : \"foo\" }", Issue700Bean.class);
+        assertNotNull(value);
+    }
 }
diff --git a/src/test/org/codehaus/jackson/map/introspect/TestPOJOPropertiesCollector.java b/src/test/org/codehaus/jackson/map/introspect/TestPOJOPropertiesCollector.java
index 1fddf00..5cedb3b 100644
--- a/src/test/org/codehaus/jackson/map/introspect/TestPOJOPropertiesCollector.java
+++ b/src/test/org/codehaus/jackson/map/introspect/TestPOJOPropertiesCollector.java
@@ -103,6 +103,18 @@
         public void setD(int value) { }
         public void setA(int value) { }
     }
+
+    // [JACKSON-700]: test property type detection, selection
+    static class TypeTestBean
+    {
+        protected Long value;
+
+        @JsonCreator
+        public TypeTestBean(@JsonProperty("value") String value) { }
+
+        // If you remove this method, the test will pass
+        public Integer getValue() { return 0; }
+    }
     
     /*
     /**********************************************************
@@ -254,7 +266,29 @@
         assertEquals("c", props.get(2).getName());
         assertEquals("d", props.get(3).getName());
     }
-    
+
+    public void testSimpleWithType()
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        // first for serialization; should base choice on getter
+        POJOPropertiesCollector coll = collector(mapper, TypeTestBean.class, true);
+        List<BeanPropertyDefinition> props = coll.getProperties();
+        assertEquals(1, props.size());
+        assertEquals("value", props.get(0).getName());
+        AnnotatedMember m = props.get(0).getAccessor();
+        assertTrue(m instanceof AnnotatedMethod);
+        assertEquals(Integer.class, m.getRawType());
+
+        // then for deserialization; prefer ctor param
+        coll = collector(mapper, TypeTestBean.class, false);
+        props = coll.getProperties();
+        assertEquals(1, props.size());
+        assertEquals("value", props.get(0).getName());
+        m = props.get(0).getMutator();
+        assertEquals(AnnotatedParameter.class, m.getClass());
+        assertEquals(String.class, m.getRawType());
+    }
+
     /*
     /**********************************************************
     /* Helper methods
@@ -271,7 +305,11 @@
     {
         BasicClassIntrospector bci = new BasicClassIntrospector();
         // no real difference between serialization, deserialization, at least here
-        return bci.collectProperties(mapper.getSerializationConfig(),
-                mapper.constructType(cls), null, forSerialization);
+        if (forSerialization) {
+            return bci.collectProperties(mapper.getSerializationConfig(),
+                    mapper.constructType(cls), null, true);
+        }
+        return bci.collectProperties(mapper.getDeserializationConfig(),
+                mapper.constructType(cls), null, false);
     }
 }