• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.deser;
2 
3 import java.io.IOException;
4 import java.util.*;
5 
6 import com.fasterxml.jackson.core.*;
7 import com.fasterxml.jackson.databind.*;
8 import com.fasterxml.jackson.databind.cfg.CoercionAction;
9 import com.fasterxml.jackson.databind.deser.impl.*;
10 import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
11 import com.fasterxml.jackson.databind.util.IgnorePropertiesUtil;
12 import com.fasterxml.jackson.databind.util.NameTransformer;
13 import com.fasterxml.jackson.databind.util.TokenBuffer;
14 
15 /**
16  * Class that handles deserialization using a separate
17  * Builder class, which is used for data binding and
18  * produces actual deserialized value at the end
19  * of data binding.
20  *<p>
21  * Note on implementation: much of code has been copied from
22  * {@link BeanDeserializer}; there may be opportunities to
23  * refactor this in future.
24  */
25 public class BuilderBasedDeserializer
26     extends BeanDeserializerBase
27 {
28     private static final long serialVersionUID = 1L;
29 
30     protected final AnnotatedMethod _buildMethod;
31 
32     /**
33      * Type that the builder will produce, target type; as opposed to
34      * `handledType()` which refers to Builder class.
35      *
36      * @since 2.9
37      */
38     protected final JavaType _targetType;
39 
40     /*
41     /**********************************************************
42     /* Life-cycle, construction, initialization
43     /**********************************************************
44      */
45 
46     /**
47      * Constructor used by {@link BeanDeserializerBuilder}.
48      */
BuilderBasedDeserializer(BeanDeserializerBuilder builder, BeanDescription beanDesc, JavaType targetType, BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, Set<String> ignorableProps, boolean ignoreAllUnknown, boolean hasViews)49     public BuilderBasedDeserializer(BeanDeserializerBuilder builder,
50             BeanDescription beanDesc, JavaType targetType,
51             BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs,
52             Set<String> ignorableProps, boolean ignoreAllUnknown,
53             boolean hasViews)
54     {
55         this(builder, beanDesc, targetType, properties, backRefs, ignorableProps, ignoreAllUnknown, null, hasViews);
56     }
57 
58     /**
59      * @since 2.12
60      */
BuilderBasedDeserializer(BeanDeserializerBuilder builder, BeanDescription beanDesc, JavaType targetType, BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, Set<String> ignorableProps, boolean ignoreAllUnknown, Set<String> includableProps, boolean hasViews)61     public BuilderBasedDeserializer(BeanDeserializerBuilder builder,
62                                     BeanDescription beanDesc, JavaType targetType,
63                                     BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs,
64                                     Set<String> ignorableProps, boolean ignoreAllUnknown, Set<String> includableProps,
65                                     boolean hasViews)
66     {
67         super(builder, beanDesc, properties, backRefs,
68                 ignorableProps, ignoreAllUnknown, includableProps, hasViews);
69         _targetType = targetType;
70         _buildMethod = builder.getBuildMethod();
71         // 05-Mar-2012, tatu: Cannot really make Object Ids work with builders, not yet anyway
72         if (_objectIdReader != null) {
73             throw new IllegalArgumentException("Cannot use Object Id with Builder-based deserialization (type "
74                     +beanDesc.getType()+")");
75         }
76     }
77 
78     /**
79      * @deprecated Since 2.9
80      */
81     @Deprecated
BuilderBasedDeserializer(BeanDeserializerBuilder builder, BeanDescription beanDesc, BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, Set<String> ignorableProps, boolean ignoreAllUnknown, boolean hasViews)82     public BuilderBasedDeserializer(BeanDeserializerBuilder builder,
83             BeanDescription beanDesc,
84             BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs,
85             Set<String> ignorableProps, boolean ignoreAllUnknown,
86             boolean hasViews)
87     {
88         this(builder, beanDesc,
89                 beanDesc.getType(), // Wrong! But got no access via `BeanDeserializerBuilder`
90                 properties, backRefs, ignorableProps, ignoreAllUnknown, hasViews);
91     }
92 
93     /**
94      * Copy-constructor that can be used by sub-classes to allow
95      * copy-on-write styling copying of settings of an existing instance.
96      */
BuilderBasedDeserializer(BuilderBasedDeserializer src)97     protected BuilderBasedDeserializer(BuilderBasedDeserializer src)
98     {
99         this(src, src._ignoreAllUnknown);
100     }
101 
BuilderBasedDeserializer(BuilderBasedDeserializer src, boolean ignoreAllUnknown)102     protected BuilderBasedDeserializer(BuilderBasedDeserializer src, boolean ignoreAllUnknown)
103     {
104         super(src, ignoreAllUnknown);
105         _buildMethod = src._buildMethod;
106         _targetType = src._targetType;
107     }
108 
BuilderBasedDeserializer(BuilderBasedDeserializer src, NameTransformer unwrapper)109     protected BuilderBasedDeserializer(BuilderBasedDeserializer src, NameTransformer unwrapper) {
110         super(src, unwrapper);
111         _buildMethod = src._buildMethod;
112         _targetType = src._targetType;
113     }
114 
BuilderBasedDeserializer(BuilderBasedDeserializer src, ObjectIdReader oir)115     public BuilderBasedDeserializer(BuilderBasedDeserializer src, ObjectIdReader oir) {
116         super(src, oir);
117         _buildMethod = src._buildMethod;
118         _targetType = src._targetType;
119     }
120 
BuilderBasedDeserializer(BuilderBasedDeserializer src, Set<String> ignorableProps)121     public BuilderBasedDeserializer(BuilderBasedDeserializer src, Set<String> ignorableProps) {
122         this(src, ignorableProps, src._includableProps);
123     }
124 
BuilderBasedDeserializer(BuilderBasedDeserializer src, Set<String> ignorableProps, Set<String> includableProps)125     public BuilderBasedDeserializer(BuilderBasedDeserializer src, Set<String> ignorableProps, Set<String> includableProps) {
126         super(src, ignorableProps, includableProps);
127         _buildMethod = src._buildMethod;
128         _targetType = src._targetType;
129     }
130 
BuilderBasedDeserializer(BuilderBasedDeserializer src, BeanPropertyMap props)131     public BuilderBasedDeserializer(BuilderBasedDeserializer src, BeanPropertyMap props) {
132         super(src, props);
133         _buildMethod = src._buildMethod;
134         _targetType = src._targetType;
135     }
136 
137     @Override
unwrappingDeserializer(NameTransformer unwrapper)138     public JsonDeserializer<Object> unwrappingDeserializer(NameTransformer unwrapper)
139     {
140         /* main thing really is to just enforce ignoring of unknown
141          * properties; since there may be multiple unwrapped values
142          * and properties for all may be interleaved...
143          */
144         return new BuilderBasedDeserializer(this, unwrapper);
145     }
146 
147     @Override
withObjectIdReader(ObjectIdReader oir)148     public BeanDeserializerBase withObjectIdReader(ObjectIdReader oir) {
149         return new BuilderBasedDeserializer(this, oir);
150     }
151 
152     @Override
withByNameInclusion(Set<String> ignorableProps, Set<String> includableProps)153     public BeanDeserializerBase withByNameInclusion(Set<String> ignorableProps,
154             Set<String> includableProps) {
155         return new BuilderBasedDeserializer(this, ignorableProps, includableProps);
156     }
157 
158     @Override
withIgnoreAllUnknown(boolean ignoreUnknown)159     public BeanDeserializerBase withIgnoreAllUnknown(boolean ignoreUnknown) {
160         return new BuilderBasedDeserializer(this, ignoreUnknown);
161     }
162 
163     @Override
withBeanProperties(BeanPropertyMap props)164     public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) {
165         return new BuilderBasedDeserializer(this, props);
166     }
167 
168     @Override
asArrayDeserializer()169     protected BeanDeserializerBase asArrayDeserializer() {
170         SettableBeanProperty[] props = _beanProperties.getPropertiesInInsertionOrder();
171         return new BeanAsArrayBuilderDeserializer(this, _targetType, props, _buildMethod);
172     }
173 
174     /*
175     /**********************************************************
176     /* JsonDeserializer implementation
177     /**********************************************************
178      */
179 
180     @Override // since 2.9
supportsUpdate(DeserializationConfig config)181     public Boolean supportsUpdate(DeserializationConfig config) {
182         // 26-Oct-2016, tatu: No, we can't merge Builder-based POJOs as of now
183         return Boolean.FALSE;
184     }
185 
186     /*
187     /**********************************************************
188     /* JsonDeserializer implementation
189     /**********************************************************
190      */
191 
finishBuild(DeserializationContext ctxt, Object builder)192     protected Object finishBuild(DeserializationContext ctxt, Object builder)
193             throws IOException
194     {
195         // As per [databind#777], allow returning builder itself
196         if (null == _buildMethod) {
197             return builder;
198         }
199         try {
200             return _buildMethod.getMember().invoke(builder, (Object[]) null);
201         } catch (Exception e) {
202             return wrapInstantiationProblem(e, ctxt);
203         }
204     }
205 
206     /**
207      * Main deserialization method for bean-based objects (POJOs).
208      */
209     @Override
deserialize(JsonParser p, DeserializationContext ctxt)210     public Object deserialize(JsonParser p, DeserializationContext ctxt)
211         throws IOException
212     {
213         // common case first:
214         if (p.isExpectedStartObjectToken()) {
215             JsonToken t = p.nextToken();
216             if (_vanillaProcessing) {
217                 return finishBuild(ctxt, vanillaDeserialize(p, ctxt, t));
218             }
219             return finishBuild(ctxt, deserializeFromObject(p, ctxt));
220         }
221         // and then others, generally requiring use of @JsonCreator
222         switch (p.currentTokenId()) {
223         case JsonTokenId.ID_STRING:
224             return finishBuild(ctxt, deserializeFromString(p, ctxt));
225         case JsonTokenId.ID_NUMBER_INT:
226             return finishBuild(ctxt, deserializeFromNumber(p, ctxt));
227         case JsonTokenId.ID_NUMBER_FLOAT:
228             return finishBuild(ctxt, deserializeFromDouble(p, ctxt));
229         case JsonTokenId.ID_EMBEDDED_OBJECT:
230             return p.getEmbeddedObject();
231         case JsonTokenId.ID_TRUE:
232         case JsonTokenId.ID_FALSE:
233             return finishBuild(ctxt, deserializeFromBoolean(p, ctxt));
234         case JsonTokenId.ID_START_ARRAY:
235             // these only work if there's a (delegating) creator, or UNWRAP_SINGLE_ARRAY
236             // [databind#2608]: Do NOT call `finishBuild()` as method implements it
237             return _deserializeFromArray(p, ctxt);
238         case JsonTokenId.ID_FIELD_NAME:
239         case JsonTokenId.ID_END_OBJECT:
240             return finishBuild(ctxt, deserializeFromObject(p, ctxt));
241         default:
242         }
243         return ctxt.handleUnexpectedToken(getValueType(ctxt), p);
244     }
245 
246     /**
247      * Secondary deserialization method, called in cases where POJO
248      * instance is created as part of deserialization, potentially
249      * after collecting some or all of the properties to set.
250      */
251     @Override
deserialize(JsonParser p, DeserializationContext ctxt, Object value)252     public Object deserialize(JsonParser p, DeserializationContext ctxt,
253     		Object value) throws IOException
254     {
255         // 26-Oct-2016, tatu: I cannot see any of making this actually
256         //    work correctly, so let's indicate problem right away
257         JavaType valueType = _targetType;
258         // Did they try to give us builder?
259         Class<?> builderRawType = handledType();
260         Class<?> instRawType = value.getClass();
261         if (builderRawType.isAssignableFrom(instRawType)) {
262             return ctxt.reportBadDefinition(valueType, String.format(
263                     "Deserialization of %s by passing existing Builder (%s) instance not supported",
264                     valueType, builderRawType.getName()));
265         }
266         return ctxt.reportBadDefinition(valueType, String.format(
267                 "Deserialization of %s by passing existing instance (of %s) not supported",
268                 valueType, instRawType.getName()));
269     }
270 
271     /*
272     /**********************************************************
273     /* Concrete deserialization methods
274     /**********************************************************
275      */
276 
277     /**
278      * Streamlined version that is only used when no "special"
279      * features are enabled.
280      */
vanillaDeserialize(JsonParser p, DeserializationContext ctxt, JsonToken t)281     private final Object vanillaDeserialize(JsonParser p,
282     		DeserializationContext ctxt, JsonToken t)
283         throws IOException
284     {
285         Object bean = _valueInstantiator.createUsingDefault(ctxt);
286         for (; p.currentToken() == JsonToken.FIELD_NAME; p.nextToken()) {
287             String propName = p.currentName();
288             // Skip field name:
289             p.nextToken();
290             SettableBeanProperty prop = _beanProperties.find(propName);
291             if (prop != null) { // normal case
292                 try {
293                     bean = prop.deserializeSetAndReturn(p, ctxt, bean);
294                 } catch (Exception e) {
295                     wrapAndThrow(e, bean, propName, ctxt);
296                 }
297             } else {
298                 handleUnknownVanilla(p, ctxt, bean, propName);
299             }
300         }
301         return bean;
302     }
303 
304     /**
305      * General version used when handling needs more advanced
306      * features.
307      */
308     @Override
deserializeFromObject(JsonParser p, DeserializationContext ctxt)309     public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt)
310         throws IOException
311     {
312         if (_nonStandardCreation) {
313             if (_unwrappedPropertyHandler != null) {
314                 return deserializeWithUnwrapped(p, ctxt);
315             }
316             if (_externalTypeIdHandler != null) {
317                 return deserializeWithExternalTypeId(p, ctxt);
318             }
319             return deserializeFromObjectUsingNonDefault(p, ctxt);
320         }
321         Object bean = _valueInstantiator.createUsingDefault(ctxt);
322         if (_injectables != null) {
323             injectValues(ctxt, bean);
324         }
325         if (_needViewProcesing) {
326             Class<?> view = ctxt.getActiveView();
327             if (view != null) {
328                 return deserializeWithView(p, ctxt, bean, view);
329             }
330         }
331         for (; p.currentToken() == JsonToken.FIELD_NAME; p.nextToken()) {
332             String propName = p.currentName();
333             // Skip field name:
334             p.nextToken();
335             SettableBeanProperty prop = _beanProperties.find(propName);
336             if (prop != null) { // normal case
337                 try {
338                     bean = prop.deserializeSetAndReturn(p, ctxt, bean);
339                 } catch (Exception e) {
340                     wrapAndThrow(e, bean, propName, ctxt);
341                 }
342                 continue;
343             }
344             handleUnknownVanilla(p, ctxt, bean, propName);
345         }
346         return bean;
347     }
348 
349     /**
350      * Method called to deserialize bean using "property-based creator":
351      * this means that a non-default constructor or factory method is
352      * called, and then possibly other setters. The trick is that
353      * values for creator method need to be buffered, first; and
354      * due to non-guaranteed ordering possibly some other properties
355      * as well.
356      *
357      * @return Builder instance constructed
358      */
359     @Override
360     @SuppressWarnings("resource")
_deserializeUsingPropertyBased(final JsonParser p, final DeserializationContext ctxt)361     protected Object _deserializeUsingPropertyBased(final JsonParser p,
362             final DeserializationContext ctxt)
363         throws IOException
364     {
365         final PropertyBasedCreator creator = _propertyBasedCreator;
366         PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader);
367         final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
368 
369         // 04-Jan-2010, tatu: May need to collect unknown properties for polymorphic cases
370         TokenBuffer unknown = null;
371 
372         JsonToken t = p.currentToken();
373         for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
374             String propName = p.currentName();
375             p.nextToken(); // to point to value
376             // creator property?
377             SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
378             if (creatorProp != null) {
379                 if ((activeView != null) && !creatorProp.visibleInView(activeView)) {
380                     p.skipChildren();
381                     continue;
382                 }
383                 // Last creator property to set?
384                 if (buffer.assignParameter(creatorProp, creatorProp.deserialize(p, ctxt))) {
385                     p.nextToken(); // to move to following FIELD_NAME/END_OBJECT
386                     Object builder;
387                     try {
388                         builder = creator.build(ctxt, buffer);
389                     } catch (Exception e) {
390                         wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
391                         continue; // never gets here
392                     }
393                     //  polymorphic?
394                     if (builder.getClass() != _beanType.getRawClass()) {
395                         return handlePolymorphic(p, ctxt, builder, unknown);
396                     }
397                     if (unknown != null) { // nope, just extra unknown stuff...
398                         builder = handleUnknownProperties(ctxt, builder, unknown);
399                     }
400                     // or just clean?
401                     return _deserialize(p, ctxt, builder);
402                 }
403                 continue;
404             }
405             // Object Id property?
406             if (buffer.readIdProperty(propName)) {
407                 continue;
408             }
409             // regular property? needs buffering
410             SettableBeanProperty prop = _beanProperties.find(propName);
411             if (prop != null) {
412                 buffer.bufferProperty(prop, prop.deserialize(p, ctxt));
413                 continue;
414             }
415             // As per [JACKSON-313], things marked as ignorable should not be
416             // passed to any setter
417             if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) {
418                 handleIgnoredProperty(p, ctxt, handledType(), propName);
419                 continue;
420             }
421             // "any property"?
422             if (_anySetter != null) {
423                 buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt));
424                 continue;
425             }
426             // Ok then, let's collect the whole field; name and value
427             if (unknown == null) {
428                 unknown = new TokenBuffer(p, ctxt);
429             }
430             unknown.writeFieldName(propName);
431             unknown.copyCurrentStructure(p);
432         }
433 
434         // We hit END_OBJECT, so:
435         Object builder;
436         try {
437             builder = creator.build(ctxt, buffer);
438         } catch (Exception e) {
439             builder = wrapInstantiationProblem(e, ctxt);
440         }
441         if (unknown != null) {
442             // polymorphic?
443             if (builder.getClass() != _beanType.getRawClass()) {
444                 return handlePolymorphic(null, ctxt, builder, unknown);
445             }
446             // no, just some extra unknown properties
447             return handleUnknownProperties(ctxt, builder, unknown);
448         }
449         return builder;
450     }
451 
452     @SuppressWarnings("resource")
_deserialize(JsonParser p, DeserializationContext ctxt, Object builder)453     protected final Object _deserialize(JsonParser p,
454             DeserializationContext ctxt, Object builder) throws IOException
455     {
456         if (_injectables != null) {
457             injectValues(ctxt, builder);
458         }
459         if (_unwrappedPropertyHandler != null) {
460             if (p.hasToken(JsonToken.START_OBJECT)) {
461                 p.nextToken();
462             }
463             TokenBuffer tokens = new TokenBuffer(p, ctxt);
464             tokens.writeStartObject();
465             return deserializeWithUnwrapped(p, ctxt, builder, tokens);
466         }
467         if (_externalTypeIdHandler != null) {
468             return deserializeWithExternalTypeId(p, ctxt, builder);
469         }
470         if (_needViewProcesing) {
471             Class<?> view = ctxt.getActiveView();
472             if (view != null) {
473                 return deserializeWithView(p, ctxt, builder, view);
474             }
475         }
476         JsonToken t = p.currentToken();
477         // 23-Mar-2010, tatu: In some cases, we start with full JSON object too...
478         if (t == JsonToken.START_OBJECT) {
479             t = p.nextToken();
480         }
481         for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
482             String propName = p.currentName();
483             // Skip field name:
484             p.nextToken();
485             SettableBeanProperty prop = _beanProperties.find(propName);
486 
487             if (prop != null) { // normal case
488                 try {
489                     builder = prop.deserializeSetAndReturn(p, ctxt, builder);
490                 } catch (Exception e) {
491                     wrapAndThrow(e, builder, propName, ctxt);
492                 }
493                 continue;
494             }
495             handleUnknownVanilla(p, ctxt, builder, propName);
496         }
497         return builder;
498     }
499 
500     @Override // since 2.11, custom implementation
_deserializeFromArray(JsonParser p, DeserializationContext ctxt)501     protected Object _deserializeFromArray(JsonParser p, DeserializationContext ctxt) throws IOException
502     {
503         // note: cannot call `_delegateDeserializer()` since order reversed here:
504         JsonDeserializer<Object> delegateDeser = _arrayDelegateDeserializer;
505         // fallback to non-array delegate
506         if ((delegateDeser != null) || ((delegateDeser = _delegateDeserializer) != null)) {
507             Object builder = _valueInstantiator.createUsingArrayDelegate(ctxt,
508                     delegateDeser.deserialize(p, ctxt));
509             if (_injectables != null) {
510                 injectValues(ctxt, builder);
511             }
512             return finishBuild(ctxt, builder);
513         }
514         final CoercionAction act = _findCoercionFromEmptyArray(ctxt);
515         final boolean unwrap = ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
516 
517         if (unwrap || (act != CoercionAction.Fail)) {
518             JsonToken t = p.nextToken();
519             if (t == JsonToken.END_ARRAY) {
520                 switch (act) {
521                 case AsEmpty:
522                     return getEmptyValue(ctxt);
523                 case AsNull:
524                 case TryConvert:
525                     return getNullValue(ctxt);
526                 default:
527                 }
528                 return ctxt.handleUnexpectedToken(getValueType(ctxt), JsonToken.START_ARRAY, p, null);
529             }
530             if (unwrap) {
531                 final Object value = deserialize(p, ctxt);
532                 if (p.nextToken() != JsonToken.END_ARRAY) {
533                     handleMissingEndArrayForSingle(p, ctxt);
534                 }
535                 return value;
536             }
537         }
538         return ctxt.handleUnexpectedToken(getValueType(ctxt), p);
539     }
540 
541     /*
542     /**********************************************************
543     /* Deserializing when we have to consider an active View
544     /**********************************************************
545      */
546 
deserializeWithView(JsonParser p, DeserializationContext ctxt, Object bean, Class<?> activeView)547     protected final Object deserializeWithView(JsonParser p, DeserializationContext ctxt,
548             Object bean, Class<?> activeView)
549         throws IOException
550     {
551         JsonToken t = p.currentToken();
552         for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
553             String propName = p.currentName();
554             // Skip field name:
555             p.nextToken();
556             SettableBeanProperty prop = _beanProperties.find(propName);
557             if (prop != null) {
558                 if (!prop.visibleInView(activeView)) {
559                     p.skipChildren();
560                     continue;
561                 }
562                 try {
563                     bean = prop.deserializeSetAndReturn(p, ctxt, bean);
564                 } catch (Exception e) {
565                     wrapAndThrow(e, bean, propName, ctxt);
566                 }
567                 continue;
568             }
569             handleUnknownVanilla(p, ctxt, bean, propName);
570         }
571         return bean;
572     }
573 
574     /*
575     /**********************************************************
576     /* Handling for cases where we have "unwrapped" values
577     /**********************************************************
578      */
579 
580     /**
581      * Method called when there are declared "unwrapped" properties
582      * which need special handling
583      */
584     @SuppressWarnings("resource")
deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt)585     protected Object deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt)
586         throws IOException
587     {
588         if (_delegateDeserializer != null) {
589             return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
590         }
591         if (_propertyBasedCreator != null) {
592             return deserializeUsingPropertyBasedWithUnwrapped(p, ctxt);
593         }
594         TokenBuffer tokens = new TokenBuffer(p, ctxt);
595         tokens.writeStartObject();
596         Object bean = _valueInstantiator.createUsingDefault(ctxt);
597 
598         if (_injectables != null) {
599             injectValues(ctxt, bean);
600         }
601 
602         final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
603         for (; p.currentToken() == JsonToken.FIELD_NAME; p.nextToken()) {
604             String propName = p.currentName();
605             p.nextToken();
606             SettableBeanProperty prop = _beanProperties.find(propName);
607             if (prop != null) { // normal case
608                 if (activeView != null && !prop.visibleInView(activeView)) {
609                     p.skipChildren();
610                     continue;
611                 }
612                 try {
613                     bean = prop.deserializeSetAndReturn(p, ctxt, bean);
614                 } catch (Exception e) {
615                     wrapAndThrow(e, bean, propName, ctxt);
616                 }
617                 continue;
618             }
619             // ignorable things should be ignored
620             if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) {
621                 handleIgnoredProperty(p, ctxt, bean, propName);
622                 continue;
623             }
624             // but... others should be passed to unwrapped property deserializers
625             tokens.writeFieldName(propName);
626             tokens.copyCurrentStructure(p);
627             // how about any setter? We'll get copies but...
628             if (_anySetter != null) {
629                 try {
630                     _anySetter.deserializeAndSet(p, ctxt, bean, propName);
631                 } catch (Exception e) {
632                     wrapAndThrow(e, bean, propName, ctxt);
633                 }
634                 continue;
635             }
636         }
637         tokens.writeEndObject();
638         return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens);
639     }
640 
641     @SuppressWarnings("resource")
deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, DeserializationContext ctxt)642     protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p,
643     		DeserializationContext ctxt)
644         throws IOException
645     {
646         final PropertyBasedCreator creator = _propertyBasedCreator;
647         PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader);
648 
649         TokenBuffer tokens = new TokenBuffer(p, ctxt);
650         tokens.writeStartObject();
651         Object builder = null;
652 
653         JsonToken t = p.currentToken();
654         for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
655             String propName = p.currentName();
656             p.nextToken(); // to point to value
657             // creator property?
658             SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
659             if (creatorProp != null) {
660                 // Last creator property to set?
661                 if (buffer.assignParameter(creatorProp, creatorProp.deserialize(p, ctxt))) {
662                     t = p.nextToken(); // to move to following FIELD_NAME/END_OBJECT
663                     try {
664                         builder = creator.build(ctxt, buffer);
665                     } catch (Exception e) {
666                         wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
667                         continue; // never gets here
668                     }
669                     if (builder.getClass() != _beanType.getRawClass()) {
670                         return handlePolymorphic(p, ctxt, builder, tokens);
671                     }
672                     return deserializeWithUnwrapped(p, ctxt, builder, tokens);
673                 }
674                 continue;
675             }
676             // Object Id property?
677             if (buffer.readIdProperty(propName)) {
678                 continue;
679             }
680             // regular property? needs buffering
681             SettableBeanProperty prop = _beanProperties.find(propName);
682             if (prop != null) {
683                 buffer.bufferProperty(prop, prop.deserialize(p, ctxt));
684                 continue;
685             }
686             if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) {
687                 handleIgnoredProperty(p, ctxt, handledType(), propName);
688                 continue;
689             }
690             tokens.writeFieldName(propName);
691             tokens.copyCurrentStructure(p);
692             // "any property"?
693             if (_anySetter != null) {
694                 buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt));
695             }
696         }
697         tokens.writeEndObject();
698 
699         // We hit END_OBJECT, so:
700         if (builder == null) {
701             try {
702                 builder = creator.build(ctxt, buffer);
703             } catch (Exception e) {
704                 return wrapInstantiationProblem(e, ctxt);
705             }
706         }
707         return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, builder, tokens);
708     }
709 
deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt, Object builder, TokenBuffer tokens)710     protected Object deserializeWithUnwrapped(JsonParser p,
711             DeserializationContext ctxt, Object builder, TokenBuffer tokens)
712         throws IOException
713     {
714         final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
715         for (JsonToken t = p.currentToken(); t == JsonToken.FIELD_NAME; t = p.nextToken()) {
716             String propName = p.currentName();
717             SettableBeanProperty prop = _beanProperties.find(propName);
718             p.nextToken();
719             if (prop != null) { // normal case
720                 if (activeView != null && !prop.visibleInView(activeView)) {
721                     p.skipChildren();
722                     continue;
723                 }
724                 try {
725                     builder = prop.deserializeSetAndReturn(p, ctxt, builder);
726                 } catch (Exception e) {
727                     wrapAndThrow(e, builder, propName, ctxt);
728                 }
729                 continue;
730             }
731             if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) {
732                 handleIgnoredProperty(p, ctxt, builder, propName);
733                 continue;
734             }
735             // but... others should be passed to unwrapped property deserializers
736             tokens.writeFieldName(propName);
737             tokens.copyCurrentStructure(p);
738             // how about any setter? We'll get copies but...
739             if (_anySetter != null) {
740                 _anySetter.deserializeAndSet(p, ctxt, builder, propName);
741             }
742         }
743         tokens.writeEndObject();
744         return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, builder, tokens);
745     }
746 
747     /*
748     /**********************************************************
749     /* Handling for cases where we have property/-ies with
750     /* external type id
751     /**********************************************************
752      */
753 
deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt)754     protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt)
755         throws IOException
756     {
757         if (_propertyBasedCreator != null) {
758             return deserializeUsingPropertyBasedWithExternalTypeId(p, ctxt);
759         }
760         return deserializeWithExternalTypeId(p, ctxt, _valueInstantiator.createUsingDefault(ctxt));
761     }
762 
deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt, Object bean)763     protected Object deserializeWithExternalTypeId(JsonParser p,
764     		DeserializationContext ctxt, Object bean)
765         throws IOException
766     {
767         final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
768         final ExternalTypeHandler ext = _externalTypeIdHandler.start();
769 
770         for (JsonToken t = p.currentToken(); t == JsonToken.FIELD_NAME; t = p.nextToken()) {
771             String propName = p.currentName();
772             t = p.nextToken();
773             SettableBeanProperty prop = _beanProperties.find(propName);
774             if (prop != null) { // normal case
775                 // May have property AND be used as external type id:
776                 if (t.isScalarValue()) {
777                     ext.handleTypePropertyValue(p, ctxt, propName, bean);
778                 }
779                 if (activeView != null && !prop.visibleInView(activeView)) {
780                     p.skipChildren();
781                     continue;
782                 }
783                 try {
784                     bean = prop.deserializeSetAndReturn(p, ctxt, bean);
785                 } catch (Exception e) {
786                     wrapAndThrow(e, bean, propName, ctxt);
787                 }
788                 continue;
789             }
790             // ignorable things should be ignored
791             if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) {
792                 handleIgnoredProperty(p, ctxt, bean, propName);
793                 continue;
794             }
795             // but others are likely to be part of external type id thingy...
796             if (ext.handlePropertyValue(p, ctxt, propName, bean)) {
797                 continue;
798             }
799             // if not, the usual fallback handling:
800             if (_anySetter != null) {
801                 try {
802                     _anySetter.deserializeAndSet(p, ctxt, bean, propName);
803                 } catch (Exception e) {
804                     wrapAndThrow(e, bean, propName, ctxt);
805                 }
806                 continue;
807             } else {
808                 // Unknown: let's call handler method
809                 handleUnknownProperty(p, ctxt, bean, propName);
810             }
811         }
812         // and when we get this far, let's try finalizing the deal:
813         return ext.complete(p, ctxt, bean);
814     }
815 
deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, DeserializationContext ctxt)816     protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p,
817     		DeserializationContext ctxt)
818         throws IOException
819     {
820         // !!! 04-Mar-2012, TODO: Need to fix -- will not work as is...
821         JavaType t = _targetType;
822         return ctxt.reportBadDefinition(t, String.format(
823                 "Deserialization (of %s) with Builder, External type id, @JsonCreator not yet implemented",
824                 t));
825     }
826 }
827