1 package com.fasterxml.jackson.databind.deser.impl;
2
3 import java.io.IOException;
4 import java.lang.annotation.Annotation;
5 import java.lang.reflect.Method;
6
7 import com.fasterxml.jackson.core.JsonParser;
8 import com.fasterxml.jackson.core.JsonToken;
9 import com.fasterxml.jackson.databind.*;
10 import com.fasterxml.jackson.databind.deser.NullValueProvider;
11 import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
12 import com.fasterxml.jackson.databind.introspect.*;
13 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
14 import com.fasterxml.jackson.databind.util.Annotations;
15
16 /**
17  * This concrete sub-class implements property that is set
18  * using regular "setter" method.
19  */

20 public final class MethodProperty
21     extends SettableBeanProperty
22 {
23     private static final long serialVersionUID = 1;
24
25     protected final AnnotatedMethod _annotated;
26     
27     /**
28      * Setter method for modifying property value; used for
29      * "regular" method-accessible properties.
30      */

31     protected final transient Method _setter;
32
33     /**
34      * @since 2.9
35      */

36     final protected boolean _skipNulls;
37     
38     public MethodProperty(BeanPropertyDefinition propDef,
39             JavaType type, TypeDeserializer typeDeser,
40             Annotations contextAnnotations, AnnotatedMethod method)
41     {
42         super(propDef, type, typeDeser, contextAnnotations);
43         _annotated = method;
44         _setter = method.getAnnotated();
45         _skipNulls = NullsConstantProvider.isSkipper(_nullProvider);
46     }
47
48     protected MethodProperty(MethodProperty src, JsonDeserializer<?> deser,
49             NullValueProvider nva) {
50         super(src, deser, nva);
51         _annotated = src._annotated;
52         _setter = src._setter;
53         _skipNulls = NullsConstantProvider.isSkipper(nva);
54     }
55
56     protected MethodProperty(MethodProperty src, PropertyName newName) {
57         super(src, newName);
58         _annotated = src._annotated;
59         _setter = src._setter;
60         _skipNulls = src._skipNulls;
61     }
62
63     /**
64      * Constructor used for JDK Serialization when reading persisted object
65      */

66     protected MethodProperty(MethodProperty src, Method m) {
67         super(src);
68         _annotated = src._annotated;
69         _setter = m;
70         _skipNulls = src._skipNulls;
71     }
72
73     @Override
74     public SettableBeanProperty withName(PropertyName newName) {
75         return new MethodProperty(this, newName);
76     }
77     
78     @Override
79     public SettableBeanProperty withValueDeserializer(JsonDeserializer<?> deser) {
80         if (_valueDeserializer == deser) {
81             return this;
82         }
83         // 07-May-2019, tatu: As per [databind#2303], must keep VD/NVP in-sync if they were
84         NullValueProvider nvp = (_valueDeserializer == _nullProvider) ? deser : _nullProvider;
85         return new MethodProperty(this, deser, nvp);
86     }
87
88     @Override
89     public SettableBeanProperty withNullProvider(NullValueProvider nva) {
90         return new MethodProperty(this, _valueDeserializer, nva);
91     }
92
93     @Override
94     public void fixAccess(DeserializationConfig config) {
95         _annotated.fixAccess(
96                 config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
97     }
98
99     /*
100     /**********************************************************
101     /* BeanProperty impl
102     /**********************************************************
103      */

104     
105     @Override
106     public <A extends Annotation> A getAnnotation(Class<A> acls) {
107         return (_annotated == null) ? null : _annotated.getAnnotation(acls);
108     }
109
110     @Override public AnnotatedMember getMember() {  return _annotated; }
111
112     /*
113     /**********************************************************
114     /* Overridden methods
115     /**********************************************************
116      */

117
118     @Override
119     public void deserializeAndSet(JsonParser p, DeserializationContext ctxt,
120             Object instance) throws IOException
121     {
122         Object value;
123         if (p.hasToken(JsonToken.VALUE_NULL)) {
124             if (_skipNulls) {
125                 return;
126             }
127             value = _nullProvider.getNullValue(ctxt);
128         } else if (_valueTypeDeserializer == null) {
129             value = _valueDeserializer.deserialize(p, ctxt);
130             // 04-May-2018, tatu: [databind#2023] Coercion from String (mostly) can give null
131             if (value == null) {
132                 if (_skipNulls) {
133                     return;
134                 }
135                 value = _nullProvider.getNullValue(ctxt);
136             }
137         } else {
138             value = _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer);
139         }
140         try {
141             _setter.invoke(instance, value);
142         } catch (Exception e) {
143             _throwAsIOE(p, e, value);
144         }
145     }
146
147     @Override
148     public Object deserializeSetAndReturn(JsonParser p,
149             DeserializationContext ctxt, Object instance) throws IOException
150     {
151         Object value;
152         if (p.hasToken(JsonToken.VALUE_NULL)) {
153             if (_skipNulls) {
154                 return instance;
155             }
156             value = _nullProvider.getNullValue(ctxt);
157         } else if (_valueTypeDeserializer == null) {
158             value = _valueDeserializer.deserialize(p, ctxt);
159             // 04-May-2018, tatu: [databind#2023] Coercion from String (mostly) can give null
160             if (value == null) {
161                 if (_skipNulls) {
162                     return instance;
163                 }
164                 value = _nullProvider.getNullValue(ctxt);
165             }
166         } else {
167             value = _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer);
168         }
169         try {
170             Object result = _setter.invoke(instance, value);
171             return (result == null) ? instance : result;
172         } catch (Exception e) {
173             _throwAsIOE(p, e, value);
174             return null;
175         }
176     }
177
178     @Override
179     public final void set(Object instance, Object value) throws IOException
180     {
181         try {
182             _setter.invoke(instance, value);
183         } catch (Exception e) {
184             // 15-Sep-2015, tatu: How could we get a ref to JsonParser?
185             _throwAsIOE(e, value);
186         }
187     }
188
189     @Override
190     public Object setAndReturn(Object instance, Object value) throws IOException
191     {
192         try {
193             Object result = _setter.invoke(instance, value);
194             return (result == null) ? instance : result;
195         } catch (Exception e) {
196             // 15-Sep-2015, tatu: How could we get a ref to JsonParser?
197             _throwAsIOE(e, value);
198             return null;
199         }
200     }
201
202     /*
203     /**********************************************************
204     /* JDK serialization handling
205     /**********************************************************
206      */

207
208     Object readResolve() {
209         return new MethodProperty(this, _annotated.getAnnotated());
210     }
211 }
212