Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   package com.fasterxml.jackson.databind.deser;
   
   import java.util.*;
   
Abstract factory base class that can provide deserializers for standard JDK classes, including collection classes and simple heuristics for "upcasting" common collection interface types (such as java.util.Collection).

Since all simple deserializers are eagerly instantiated, and there is no additional introspection or customizability of these types, this factory is stateless.

  
  @SuppressWarnings("serial")
  public abstract class BasicDeserializerFactory
      extends DeserializerFactory
      implements java.io.Serializable
  {
      private final static Class<?> CLASS_OBJECT = Object.class;
      private final static Class<?> CLASS_STRING = String.class;
      private final static Class<?> CLASS_CHAR_BUFFER = CharSequence.class;
      private final static Class<?> CLASS_ITERABLE = Iterable.class;

    
We need a placeholder for creator properties that don't have name but are marked with `@JsonWrapped` annotation.
  
      protected final static PropertyName UNWRAPPED_CREATOR_PARAM_NAME = new PropertyName("@JsonUnwrapped");
      
      /* We do some defaulting for abstract Map classes and
       * interfaces, to avoid having to use exact types or annotations in
       * cases where the most common concrete Maps will do.
       */
      @SuppressWarnings("rawtypes")
      final static HashMap<StringClass<? extends Map>> _mapFallbacks =
          new HashMap<StringClass<? extends Map>>();
      static {
          .put(Map.class.getName(), LinkedHashMap.class);
          .put(ConcurrentMap.class.getName(), ConcurrentHashMap.class);
          .put(SortedMap.class.getName(), TreeMap.class);
  
          /* 11-Jan-2009, tatu: Let's see if we can still add support for
           *    JDK 1.6 interfaces, even if we run on 1.5. Just need to be
           *    more careful with typos, since compiler won't notice any
           *    problems...
           */
          .put("java.util.NavigableMap"TreeMap.class);
          try {
              Class<?> key = java.util.concurrent.ConcurrentNavigableMap.class;
              Class<?> value = java.util.concurrent.ConcurrentSkipListMap.class;
              @SuppressWarnings("unchecked")
                  Class<? extends Map<?,?>> mapValue = (Class<? extends Map<?,?>>) value;
              .put(key.getName(), mapValue);
          } catch (Throwable e) { // some class loading problems are Errors, others Exceptions
              ..println("Problems with (optional) types: "+e);
          }
      }
  
      /* We do some defaulting for abstract Collection classes and
       * interfaces, to avoid having to use exact types or annotations in
       * cases where the most common concrete Collection will do.
       */
      @SuppressWarnings("rawtypes")
      final static HashMap<StringClass<? extends Collection>> _collectionFallbacks =
          new HashMap<StringClass<? extends Collection>>();
      static {
          .put(Collection.class.getName(), ArrayList.class);
          .put(List.class.getName(), ArrayList.class);
          .put(Set.class.getName(), HashSet.class);
          .put(SortedSet.class.getName(), TreeSet.class);
          .put(Queue.class.getName(), LinkedList.class);
  
          // then 1.6 types:
          /* 17-May-2013, tatu: [Issue#216] Should be fine to use straight Class references EXCEPT
           *   that some godforsaken platforms (... looking at you, Android) do not
           *   include these. So, use "soft" references...
           */
          .put("java.util.Deque"LinkedList.class);
          .put("java.util.NavigableSet"TreeSet.class);
     }
     
     /*
     /**********************************************************
     /* Config
     /**********************************************************
      */
    
    
Configuration settings for this factory; immutable instance (just like this factory), new version created via copy-constructor (fluent-style)
 
     protected final DeserializerFactoryConfig _factoryConfig;
     
     /*
     /**********************************************************
     /* Life cycle
     /**********************************************************
      */
 
          = config;
     }
    
    
Method for getting current com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig.

Note that since instances are immutable, you can NOT change settings by accessing an instance and calling methods: this will simply create new instance of config object.

 
         return ;
     }
 
     protected abstract DeserializerFactory withConfig(DeserializerFactoryConfig config);
     
     /*
     /********************************************************
     /* Configuration handling: fluent factories
     /********************************************************
      */

    
Convenience method for creating a new factory instance with additional deserializer provider.
 
     @Override
     public final DeserializerFactory withAdditionalDeserializers(Deserializers additional) {
         return withConfig(.withAdditionalDeserializers(additional));
     }

    
Convenience method for creating a new factory instance with additional KeyDeserializers.
 
     @Override
         return withConfig(.withAdditionalKeyDeserializers(additional));
     }
    
    
Convenience method for creating a new factory instance with additional BeanDeserializerModifier.
 
     @Override
         return withConfig(.withDeserializerModifier(modifier));
     }

    
Convenience method for creating a new factory instance with additional com.fasterxml.jackson.databind.AbstractTypeResolver.
 
     @Override
         return withConfig(.withAbstractTypeResolver(resolver));
     }

    
Convenience method for creating a new factory instance with additional ValueInstantiators.
 
     @Override
     public final DeserializerFactory withValueInstantiators(ValueInstantiators instantiators) {
         return withConfig(.withValueInstantiators(instantiators));
     }
 
     /*
     /**********************************************************
     /* JsonDeserializerFactory impl (partial): type mappings
     /**********************************************************
      */
 
     @Override
     public JavaType mapAbstractType(DeserializationConfig configJavaType type)
         throws JsonMappingException
     {
         // first, general mappings
         while (true) {
             JavaType next = _mapAbstractType2(configtype);
             if (next == null) {
                 return type;
             }
             /* Should not have to worry about cycles; but better verify since they will invariably
              * occur... :-)
              * (also: guard against invalid resolution to a non-related type)
              */
             Class<?> prevCls = type.getRawClass();
             Class<?> nextCls = next.getRawClass();
             if ((prevCls == nextCls) || !prevCls.isAssignableFrom(nextCls)) {
                 throw new IllegalArgumentException("Invalid abstract type resolution from "+type+" to "+next+": latter is not a subtype of former");
             }
             type = next;
         }
     }

    
Method that will find abstract type mapping for specified type, doing a single lookup through registered abstract type resolvers; will not do recursive lookups.
 
     private JavaType _mapAbstractType2(DeserializationConfig configJavaType type)
         throws JsonMappingException
     {
         Class<?> currClass = type.getRawClass();
         if (.hasAbstractTypeResolvers()) {
             for (AbstractTypeResolver resolver : .abstractTypeResolvers()) {
                 JavaType concrete = resolver.findTypeMapping(configtype);
                 if (concrete != null && concrete.getRawClass() != currClass) {
                     return concrete;
                 }
             }
         }
         return null;
     }
     
     /*
     /**********************************************************
     /* JsonDeserializerFactory impl (partial): ValueInstantiators
     /**********************************************************
      */

    
Value instantiator is created both based on creator annotations, and on optional externally provided instantiators (registered through module interface).
 
     @Override
             BeanDescription beanDesc)
         throws JsonMappingException
     {
         final DeserializationConfig config = ctxt.getConfig();
 
         ValueInstantiator instantiator = null;
         // [JACKSON-633] Check @JsonValueInstantiator before anything else
         AnnotatedClass ac = beanDesc.getClassInfo();
         Object instDef = ctxt.getAnnotationIntrospector().findValueInstantiator(ac);
         if (instDef != null) {
             instantiator = _valueInstantiatorInstance(configacinstDef);
         }
         if (instantiator == null) {
             /* Second: see if some of standard Jackson/JDK types might provide value
              * instantiators.
              */
             instantiator = _findStdValueInstantiator(configbeanDesc);
             if (instantiator == null) {
                 instantiator = _constructDefaultValueInstantiator(ctxtbeanDesc);
             }
         }
         
         // finally: anyone want to modify ValueInstantiator?
         if (.hasValueInstantiators()) {
             for (ValueInstantiators insts : .valueInstantiators()) {
                 instantiator = insts.findValueInstantiator(configbeanDescinstantiator);
                 // let's do sanity check; easier to spot buggy handlers
                 if (instantiator == null) {
                     throw new JsonMappingException("Broken registered ValueInstantiators (of type "
                             +insts.getClass().getName()+"): returned null ValueInstantiator");
                 }
             }
         }
 
         // Sanity check: does the chosen instantatior have incomplete creators?
         if (instantiator.getIncompleteParameter() != null) {
             final AnnotatedParameter nonAnnotatedParam = instantiator.getIncompleteParameter();
             final AnnotatedWithParams ctor = nonAnnotatedParam.getOwner();
             throw new IllegalArgumentException("Argument #"+nonAnnotatedParam.getIndex()+" of constructor "+ctor+" has no property name annotation; must have name when multiple-paramater constructor annotated as Creator");
         }
 
         return instantiator;
     }
 
             BeanDescription beanDesc)
         throws JsonMappingException
     {
         if (beanDesc.getBeanClass() == JsonLocation.class) {
             return .;
         }
         return null;
     }

    
Method that will construct standard default ValueInstantiator using annotations (like

JsonCreator:
and visibility rules
 
             BeanDescription beanDesc)
         throws JsonMappingException
     {
         boolean fixAccess = ctxt.canOverrideAccessModifiers();
         CreatorCollector creators =  new CreatorCollector(beanDescfixAccess);
         AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
         
         // need to construct suitable visibility checker:
         final DeserializationConfig config = ctxt.getConfig();
         VisibilityChecker<?> vchecker = config.getDefaultVisibilityChecker();
         vchecker = intr.findAutoDetectVisibility(beanDesc.getClassInfo(), vchecker);
 
         /* Important: first add factory methods; then constructors, so
          * latter can override former!
          */
         _addDeserializerFactoryMethods(ctxtbeanDescvcheckerintrcreators);
         // constructors only usable on concrete types:
         if (beanDesc.getType().isConcrete()) {
             _addDeserializerConstructors(ctxtbeanDescvcheckerintrcreators);
         }
         return creators.constructValueInstantiator(config);
     }
 
             Annotated annotatedObject instDef)
         throws JsonMappingException
     {
         if (instDef == null) {
             return null;
         }
 
         ValueInstantiator inst;
         
         if (instDef instanceof ValueInstantiator) {
             return (ValueInstantiatorinstDef;
         }
         if (!(instDef instanceof Class)) {
             throw new IllegalStateException("AnnotationIntrospector returned key deserializer definition of type "
                     +instDef.getClass().getName()
                     +"; expected type KeyDeserializer or Class<KeyDeserializer> instead");
         }
         Class<?> instClass = (Class<?>)instDef;
         if (instClass == NoClass.class) {
             return null;
         }
         if (!ValueInstantiator.class.isAssignableFrom(instClass)) {
             throw new IllegalStateException("AnnotationIntrospector returned Class "+instClass.getName()
                     +"; expected Class<ValueInstantiator>");
         }
         HandlerInstantiator hi = config.getHandlerInstantiator();
         if (hi != null) {
             inst = hi.valueInstantiatorInstance(configannotatedinstClass);
             if (inst != null) {
                 return inst;
             }
         }
         return (ValueInstantiator) ClassUtil.createInstance(instClass,
                 config.canOverrideAccessModifiers());
     }
     
     protected void _addDeserializerConstructors
         (DeserializationContext ctxtBeanDescription beanDescVisibilityChecker<?> vchecker,
          AnnotationIntrospector intrCreatorCollector creators)
         throws JsonMappingException
     {
         /* First things first: the "default constructor" (zero-arg
          * constructor; whether implicit or explicit) is NOT included
          * in list of constructors, so needs to be handled separately.
          */
         AnnotatedConstructor defaultCtor = beanDesc.findDefaultConstructor();
         if (defaultCtor != null) {
             if (!creators.hasDefaultCreator() || intr.hasCreatorAnnotation(defaultCtor)) {
                 creators.setDefaultCreator(defaultCtor);
             }
         }
 
         PropertyName[] ctorPropNames = null;
         AnnotatedConstructor propertyCtor = null;
         for (BeanPropertyDefinition propDef : beanDesc.findProperties()) {
             if (propDef.getConstructorParameter() != null) {
                 AnnotatedParameter param = propDef.getConstructorParameter();
                 AnnotatedWithParams owner = param.getOwner();
                 if (owner instanceof AnnotatedConstructor) {
                     if (propertyCtor == null) {
                         propertyCtor = (AnnotatedConstructorowner;
                         ctorPropNames = new PropertyName[propertyCtor.getParameterCount()];
                     }
                     ctorPropNames[param.getIndex()] = propDef.getFullName();
                 }
             }
         }
 
         for (AnnotatedConstructor ctor : beanDesc.getConstructors()) {
             int argCount = ctor.getParameterCount();
             boolean isCreator = intr.hasCreatorAnnotation(ctor) || ctor == propertyCtor;
             boolean isVisible =  vchecker.isCreatorVisible(ctor);
             // some single-arg constructors (String, number) are auto-detected
             if (argCount == 1) {
                 PropertyName name = (ctor == propertyCtor) ? ctorPropNames[0] : null;
                 _handleSingleArgumentConstructor(ctxtbeanDescvcheckerintrcreators,
                         ctorisCreatorisVisiblename);
                 continue;
             }
             if (!isCreator && !isVisible) {
                 continue;
             }
 
             // [JACKSON-541] improved handling a bit so:
             // 2 or more args; all params must have name annotations
             // ... or @JacksonInject (or equivalent)
             /* [JACKSON-711] One more possibility; can have 1 or more injectables, and
              * exactly one non-annotated parameter: if so, it's still delegating.
              */
             AnnotatedParameter nonAnnotatedParam = null;
             int namedCount = 0;
             int injectCount = 0;
             CreatorProperty[] properties = new CreatorProperty[argCount];
             for (int i = 0; i < argCount; ++i) {
                 AnnotatedParameter param = ctor.getParameter(i);
                 PropertyName name = null;
                 if (ctor == propertyCtor) {
                     name = ctorPropNames[i];
                 }
                 if (name == null) {
                     name = (param == null) ? null : intr.findNameForDeserialization(param);
                 }
                 Object injectId = intr.findInjectableValueId(param);
                 if (name != null && name.hasSimpleName()) {
                     ++namedCount;
                     properties[i] = constructCreatorProperty(ctxtbeanDescnameiparaminjectId);
                 } else if (injectId != null) { // injectable
                     ++injectCount;
                     properties[i] = constructCreatorProperty(ctxtbeanDescnameiparaminjectId);
                 } else {
                     NameTransformer unwrapper = intr.findUnwrappingNameTransformer(param);
                     if (unwrapper != null) { // [Issue#265]: allow unwrapped properties
                         properties[i] = constructCreatorProperty(ctxtbeanDesc,
                                 iparamnull);
                         ++namedCount;
                     } else {
                         if (nonAnnotatedParam == null) {
                             nonAnnotatedParam = param;
                         }
                     }
                 }
             }
 
             // Ok: if named or injectable, we have more work to do
             if (isCreator || namedCount > 0 || injectCount > 0) {
                 // simple case; everything covered:
                 if ((namedCount + injectCount) == argCount) {
                     creators.addPropertyCreator(ctorproperties);
                 } else if ((namedCount == 0) && ((injectCount + 1) == argCount)) {
                     // [712] secondary: all but one injectable, one un-annotated (un-named)
                     creators.addDelegatingCreator(ctorproperties);
                 } else { // otherwise, record the incomplete parameter for later error messaging.
                     creators.addIncompeteParameter(nonAnnotatedParam);
                 }
             }
         }
     }
 
     protected boolean _handleSingleArgumentConstructor(DeserializationContext ctxt,
             BeanDescription beanDescVisibilityChecker<?> vchecker,
             AnnotationIntrospector intrCreatorCollector creators,
             AnnotatedConstructor ctorboolean isCreatorboolean isVisible,
             PropertyName name)
         throws JsonMappingException
     {
         // note: if we do have parameter name, it'll be "property constructor":
         AnnotatedParameter param = ctor.getParameter(0);
         if (name == null) {
             name = (param == null) ? null : intr.findNameForDeserialization(param);
         }
         Object injectId = intr.findInjectableValueId(param);
     
         if ((injectId != null) || (name != null && name.hasSimpleName())) { // property-based
             // We know there's a name and it's only 1 parameter.
             CreatorProperty[] properties = new CreatorProperty[1];
             properties[0] = constructCreatorProperty(ctxtbeanDescname, 0, paraminjectId);
             creators.addPropertyCreator(ctorproperties);
             return true;
         }
     
         // otherwise either 'simple' number, String, or general delegate:
         Class<?> type = ctor.getRawParameterType(0);
         if (type == String.class) {
             if (isCreator || isVisible) {
                 creators.addStringCreator(ctor);
             }
             return true;
         }
         if (type == int.class || type == Integer.class) {
             if (isCreator || isVisible) {
                 creators.addIntCreator(ctor);
             }
             return true;
         }
         if (type == long.class || type == Long.class) {
             if (isCreator || isVisible) {
                 creators.addLongCreator(ctor);
             }
             return true;
         }
         if (type == double.class || type == Double.class) {
             if (isCreator || isVisible) {
                 creators.addDoubleCreator(ctor);
             }
             return true;
         }
     
         // Delegating Creator ok iff it has @JsonCreator (etc)
         if (isCreator) {
             creators.addDelegatingCreator(ctornull);
             return true;
         }
         return false;
     }
 
     protected void _addDeserializerFactoryMethods
         (DeserializationContext ctxtBeanDescription beanDescVisibilityChecker<?> vchecker,
          AnnotationIntrospector intrCreatorCollector creators)
         throws JsonMappingException
     {
         final DeserializationConfig config = ctxt.getConfig();
         for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) {
             boolean isCreator = intr.hasCreatorAnnotation(factory);
             int argCount = factory.getParameterCount();
             // zero-arg methods must be annotated; if so, are "default creators" [JACKSON-850]
             if (argCount == 0) {
                 if (isCreator) {
                     creators.setDefaultCreator(factory);
                 }
                 continue;
             }
             // some single-arg factory methods (String, number) are auto-detected
             if (argCount == 1) {
                 AnnotatedParameter param = factory.getParameter(0);
                 PropertyName pn = (param == null) ? null : intr.findNameForDeserialization(param);
                 String name = (pn == null) ? null : pn.getSimpleName();
                 Object injectId = intr.findInjectableValueId(param);
 
                 if ((injectId == null) && (name == null || name.length() == 0)) { // not property based
                     _handleSingleArgumentFactory(configbeanDescvcheckerintrcreators,
                             factoryisCreator);
                     // otherwise just ignored
                     continue;
                 }
                 // fall through if there's name
             } else {
                 // more than 2 args, must be @JsonCreator
                 if (!intr.hasCreatorAnnotation(factory)) {
                     continue;
                 }
             }
             // 1 or more args; all params must have name annotations
             AnnotatedParameter nonAnnotatedParam = null;            
             CreatorProperty[] properties = new CreatorProperty[argCount];
             int namedCount = 0;
             int injectCount = 0;            
             for (int i = 0; i < argCount; ++i) {
                 AnnotatedParameter param = factory.getParameter(i);
                 PropertyName name = (param == null) ? null : intr.findNameForDeserialization(param);
                 Object injectId = intr.findInjectableValueId(param);
                 if (name != null && name.hasSimpleName()) {
                     ++namedCount;
                     properties[i] = constructCreatorProperty(ctxtbeanDescnameiparaminjectId);
                 } else if (injectId != null) {
                     ++injectCount;
                     properties[i] = constructCreatorProperty(ctxtbeanDescnameiparaminjectId);
                 } else {
                     NameTransformer unwrapper = intr.findUnwrappingNameTransformer(param);
                     if (unwrapper != null) {
                         properties[i] = constructCreatorProperty(ctxtbeanDesciparamnull);
                         ++namedCount;
                     } else {
                         if (nonAnnotatedParam == null) {
                             nonAnnotatedParam = param;
                         }
                     }
                 }
             }
 
             // Ok: if named or injectable, we have more work to do
             if (isCreator || namedCount > 0 || injectCount > 0) {
                 // simple case; everything covered:
                 if ((namedCount + injectCount) == argCount) {
                     creators.addPropertyCreator(factoryproperties);
                 } else if ((namedCount == 0) && ((injectCount + 1) == argCount)) {
                     // [712] secondary: all but one injectable, one un-annotated (un-named)
                     creators.addDelegatingCreator(factoryproperties);
                 } else { // otherwise, epic fail
                     throw new IllegalArgumentException("Argument #"+nonAnnotatedParam.getIndex()
                             +" of factory method "+factory+" has no property name annotation; must have name when multiple-paramater constructor annotated as Creator");
                 }
             }
         }
     }
 
     protected boolean _handleSingleArgumentFactory(DeserializationConfig config,
             BeanDescription beanDescVisibilityChecker<?> vchecker,
             AnnotationIntrospector intrCreatorCollector creators,
             AnnotatedMethod factoryboolean isCreator)
         throws JsonMappingException
     {
         Class<?> type = factory.getRawParameterType(0);
         
         if (type == String.class) {
             if (isCreator || vchecker.isCreatorVisible(factory)) {
                 creators.addStringCreator(factory);
             }
             return true;
         }
         if (type == int.class || type == Integer.class) {
             if (isCreator || vchecker.isCreatorVisible(factory)) {
                 creators.addIntCreator(factory);
             }
             return true;
         }
         if (type == long.class || type == Long.class) {
             if (isCreator || vchecker.isCreatorVisible(factory)) {
                 creators.addLongCreator(factory);
             }
             return true;
         }
         if (type == double.class || type == Double.class) {
             if (isCreator || vchecker.isCreatorVisible(factory)) {
                 creators.addDoubleCreator(factory);
             }
             return true;
         }
         if (type == boolean.class || type == Boolean.class) {
             if (isCreator || vchecker.isCreatorVisible(factory)) {
                 creators.addBooleanCreator(factory);
             }
             return true;
         }
         if (intr.hasCreatorAnnotation(factory)) {
             creators.addDelegatingCreator(factorynull);
             return true;
         }
         return false;
     }

    
Method that will construct a property object that represents a logical property passed via Creator (constructor or static factory method)
 
             BeanDescription beanDescPropertyName nameint index,
             AnnotatedParameter param,
             Object injectableValueId)
         throws JsonMappingException
     {
         final DeserializationConfig config = ctxt.getConfig();
         final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
         PropertyMetadata metadata;
 
         {
             Boolean b = (intr == null) ? null : intr.hasRequiredMarker(param);
             boolean req = (b != null && b.booleanValue());
             String desc = (intr == null) ? null : intr.findPropertyDescription(param);
             metadata = PropertyMetadata.construct(reqdesc);
         }
             
         JavaType t0 = config.getTypeFactory().constructType(param.getParameterType(), beanDesc.bindingsForBeanType());
         BeanProperty.Std property = new BeanProperty.Std(namet0,
                 intr.findWrapperName(param),
                 beanDesc.getClassAnnotations(), parammetadata);
         JavaType type = resolveType(ctxtbeanDesct0param);
         if (type != t0) {
             property = property.withType(type);
         }
         // Is there an annotation that specifies exact deserializer?
         JsonDeserializer<Objectdeser = findDeserializerFromAnnotation(ctxtparam);
         // If yes, we are mostly done:
         type = modifyTypeByAnnotation(ctxtparamtype);
 
         // Type deserializer: either comes from property (and already resolved)
         TypeDeserializer typeDeser = (TypeDeserializertype.getTypeHandler();
         // or if not, based on type being referenced:
         if (typeDeser == null) {
             typeDeser = findTypeDeserializer(configtype);
         }
 
         CreatorProperty prop = new CreatorProperty(nametypeproperty.getWrapperName(),
                 typeDeserbeanDesc.getClassAnnotations(), paramindexinjectableValueId,
                 metadata);
         if (deser != null) {
             prop = prop.withValueDeserializer(deser);
         }
         return prop;
     }
     
     /*
     /**********************************************************
     /* JsonDeserializerFactory impl: array deserializers
     /**********************************************************
      */
         
     @Override
             ArrayType typefinal BeanDescription beanDesc)
         throws JsonMappingException
     {
         final DeserializationConfig config = ctxt.getConfig();
         JavaType elemType = type.getContentType();
         
         // Very first thing: is deserializer hard-coded for elements?
         JsonDeserializer<ObjectcontentDeser = elemType.getValueHandler();
         // Then optional type info (1.5): if type has been resolved, we may already know type deserializer:
         TypeDeserializer elemTypeDeser = elemType.getTypeHandler();
         // but if not, may still be possible to find:
         if (elemTypeDeser == null) {
             elemTypeDeser = findTypeDeserializer(configelemType);
         }
         // 23-Nov-2010, tatu: Custom array deserializer?
         JsonDeserializer<?>  deser = _findCustomArrayDeserializer(type,
                 configbeanDescelemTypeDesercontentDeser);
         if (deser == null) {
             if (contentDeser == null) {
                 Class<?> raw = elemType.getRawClass();
                 if (elemType.isPrimitive()) {
                     return PrimitiveArrayDeserializers.forType(raw);
                 } else if (raw == String.class) {
                     return .;
                 }
             }
             deser = new ObjectArrayDeserializer(typecontentDeserelemTypeDeser);
         }
         // and then new with 2.2: ability to post-process it too (Issue#120)
         if (.hasDeserializerModifiers()) {
             for (BeanDeserializerModifier mod : .deserializerModifiers()) {
                 deser = mod.modifyArrayDeserializer(configtypebeanDescdeser);
             }
         }
         return deser;
     }
 
             DeserializationConfig configBeanDescription beanDesc,
             TypeDeserializer elementTypeDeserializerJsonDeserializer<?> elementDeserializer)
         throws JsonMappingException
     {
         for (Deserializers d  : .deserializers()) {
             JsonDeserializer<?> deser = d.findArrayDeserializer(typeconfig,
                     beanDescelementTypeDeserializerelementDeserializer);
             if (deser != null) {
                 return deser;
             }
         }
         return null;
     }
     
     /*
     /**********************************************************
     /* JsonDeserializerFactory impl: Collection(-like) deserializers
     /**********************************************************
      */
 
     @Override
             CollectionType typeBeanDescription beanDesc)
         throws JsonMappingException
     {
         JavaType contentType = type.getContentType();
         // Very first thing: is deserializer hard-coded for elements?
         JsonDeserializer<ObjectcontentDeser = contentType.getValueHandler();
         final DeserializationConfig config = ctxt.getConfig();
 
         // Then optional type info (1.5): if type has been resolved, we may already know type deserializer:
         TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
         // but if not, may still be possible to find:
         if (contentTypeDeser == null) {
             contentTypeDeser = findTypeDeserializer(configcontentType);
         }
 
         // 23-Nov-2010, tatu: Custom deserializer?
         JsonDeserializer<?> deser = _findCustomCollectionDeserializer(type,
                 configbeanDesccontentTypeDesercontentDeser);
         if (deser == null) {
             Class<?> collectionClass = type.getRawClass();
             if (contentDeser == null) { // not defined by annotation
                 // One special type: EnumSet:
                 if (EnumSet.class.isAssignableFrom(collectionClass)) {
                     deser = new EnumSetDeserializer(contentTypenull);
                 }
             }
         }
         
         /* One twist: if we are being asked to instantiate an interface or
          * abstract Collection, we need to either find something that implements
          * the thing, or give up.
          *
          * Note that we do NOT try to guess based on secondary interfaces
          * here; that would probably not work correctly since casts would
          * fail later on (as the primary type is not the interface we'd
          * be implementing)
          */
         if (deser == null) {
             if (type.isInterface() || type.isAbstract()) {
                 CollectionType implType = _mapAbstractCollectionType(typeconfig);
                 if (implType == null) {
                     // [Issue#292]: Actually, may be fine, but only if polymorphich deser enabled
                     if (type.getTypeHandler() == null) {
                         throw new IllegalArgumentException("Can not find a deserializer for non-concrete Collection type "+type);
                     }
                     deser = AbstractDeserializer.constructForNonPOJO(beanDesc);
                 } else {
                     type = implType;
                     // But if so, also need to re-check creators...
                     beanDesc = config.introspectForCreation(type);
                 }
             }
             if (deser == null) {
                 ValueInstantiator inst = findValueInstantiator(ctxtbeanDesc);
                 if (!inst.canCreateUsingDefault()) {
                     // [Issue#161]: No default constructor for ArrayBlockingQueue...
                     if (type.getRawClass() == ArrayBlockingQueue.class) {
                         return new ArrayBlockingQueueDeserializer(typecontentDesercontentTypeDeserinstnull);
                     }
                 }
                 // 13-Dec-2010, tatu: Can use more optimal deserializer if content type is String, so:
                 if (contentType.getRawClass() == String.class) {
                     // no value type deserializer because Strings are one of natural/native types:
                     deser = new StringCollectionDeserializer(typecontentDeserinst);
                 } else {
                     deser = new CollectionDeserializer(typecontentDesercontentTypeDeserinst);
                 }
             }
         }
         // and then new with 2.2: ability to post-process it too (Issue#120)
         if (.hasDeserializerModifiers()) {
             for (BeanDeserializerModifier mod : .deserializerModifiers()) {
                 deser = mod.modifyCollectionDeserializer(configtypebeanDescdeser);
             }
         }
         return deser;
     }
 
     {
         Class<?> collectionClass = type.getRawClass();
         collectionClass = .get(collectionClass.getName());
         if (collectionClass == null) {
             return null;
         }
         return (CollectionTypeconfig.constructSpecializedType(typecollectionClass);
     }
 
             DeserializationConfig configBeanDescription beanDesc,
             TypeDeserializer elementTypeDeserializerJsonDeserializer<?> elementDeserializer)
         throws JsonMappingException
     {
         for (Deserializers d  : .deserializers()) {
             JsonDeserializer<?> deser = d.findCollectionDeserializer(typeconfigbeanDesc,
                     elementTypeDeserializerelementDeserializer);
             if (deser != null) {
                 return deser;
             }
         }
         return null;
     }
     
     // Copied almost verbatim from "createCollectionDeserializer" -- should try to share more code
     @Override
             CollectionLikeType typefinal BeanDescription beanDesc)
         throws JsonMappingException
     {
         JavaType contentType = type.getContentType();
         // Very first thing: is deserializer hard-coded for elements?
         JsonDeserializer<ObjectcontentDeser = contentType.getValueHandler();
         final DeserializationConfig config = ctxt.getConfig();
 
         // Then optional type info (1.5): if type has been resolved, we may already know type deserializer:
         TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
         // but if not, may still be possible to find:
         if (contentTypeDeser == null) {
             contentTypeDeser = findTypeDeserializer(configcontentType);
         }
         JsonDeserializer<?> deser = _findCustomCollectionLikeDeserializer(typeconfigbeanDesc,
                 contentTypeDesercontentDeser);
         if (deser != null) {
             // and then new with 2.2: ability to post-process it too (Issue#120)
             if (.hasDeserializerModifiers()) {
                 for (BeanDeserializerModifier mod : .deserializerModifiers()) {
                     deser = mod.modifyCollectionLikeDeserializer(configtypebeanDescdeser);
                 }
             }
         }
         return deser;
     }
 
             DeserializationConfig configBeanDescription beanDesc,
             TypeDeserializer elementTypeDeserializerJsonDeserializer<?> elementDeserializer)
         throws JsonMappingException
     {
         for (Deserializers d  : .deserializers()) {
             JsonDeserializer<?> deser = d.findCollectionLikeDeserializer(typeconfigbeanDesc,
                     elementTypeDeserializerelementDeserializer);
             if (deser != null) {
                 return deser;
             }
         }
         return null;
     }
 
     /*
     /**********************************************************
     /* JsonDeserializerFactory impl: Map(-like) deserializers
     /**********************************************************
      */
     
     @Override
             MapType typeBeanDescription beanDesc)
         throws JsonMappingException
     {
         final DeserializationConfig config = ctxt.getConfig();
         JavaType keyType = type.getKeyType();
         JavaType contentType = type.getContentType();
         
         // First: is there annotation-specified deserializer for values?
         @SuppressWarnings("unchecked")
         JsonDeserializer<ObjectcontentDeser = (JsonDeserializer<Object>) contentType.getValueHandler();
         
         // Ok: need a key deserializer (null indicates 'default' here)
         KeyDeserializer keyDes = (KeyDeserializerkeyType.getValueHandler();
         // Then optional type info (1.5); either attached to type, or resolved separately:
         TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
         // but if not, may still be possible to find:
         if (contentTypeDeser == null) {
             contentTypeDeser = findTypeDeserializer(configcontentType);
         }
         
         // 23-Nov-2010, tatu: Custom deserializer?
         JsonDeserializer<?> deser = _findCustomMapDeserializer(typeconfigbeanDesc,
                 keyDescontentTypeDesercontentDeser);
 
         if (deser == null) {
             // Value handling is identical for all, but EnumMap requires special handling for keys
             Class<?> mapClass = type.getRawClass();
             if (EnumMap.class.isAssignableFrom(mapClass)) {
                 Class<?> kt = keyType.getRawClass();
                 if (kt == null || !kt.isEnum()) {
                     throw new IllegalArgumentException("Can not construct EnumMap; generic (key) type not available");
                 }
                 deser = new EnumMapDeserializer(typenullcontentDesercontentTypeDeser);
             }
 
             // Otherwise, generic handler works ok.
     
             /* But there is one more twist: if we are being asked to instantiate
              * an interface or abstract Map, we need to either find something
              * that implements the thing, or give up.
              *
              * Note that we do NOT try to guess based on secondary interfaces
              * here; that would probably not work correctly since casts would
              * fail later on (as the primary type is not the interface we'd
              * be implementing)
              */
             if (deser == null) {
                 if (type.isInterface() || type.isAbstract()) {
                     @SuppressWarnings("rawtypes")
                     Class<? extends Mapfallback = .get(mapClass.getName());
                     if (fallback != null) {
                         mapClass = fallback;
                         type = (MapTypeconfig.constructSpecializedType(typemapClass);
                         // But if so, also need to re-check creators...
                         beanDesc = config.introspectForCreation(type);
                     } else {
                         // [Issue#292]: Actually, may be fine, but only if polymorphich deser enabled
                         if (type.getTypeHandler() == null) {
                             throw new IllegalArgumentException("Can not find a deserializer for non-concrete Map type "+type);
                         }
                         deser = AbstractDeserializer.constructForNonPOJO(beanDesc);
                     }
                 }
                 if (deser == null) {
                     ValueInstantiator inst = findValueInstantiator(ctxtbeanDesc);
                     MapDeserializer md = new MapDeserializer(typeinstkeyDescontentDesercontentTypeDeser);
                     md.setIgnorableProperties(config.getAnnotationIntrospector().findPropertiesToIgnore(beanDesc.getClassInfo()));
                     deser = md;
                 }
             }
         }
         // and then new with 2.2: ability to post-process it too (Issue#120)
         if (.hasDeserializerModifiers()) {
            for (BeanDeserializerModifier mod : .deserializerModifiers()) {
                deser = mod.modifyMapDeserializer(configtypebeanDescdeser);
            }
        }
        return deser;
    }
    // Copied almost verbatim from "createMapDeserializer" -- should try to share more code
    @Override
            MapLikeType typefinal BeanDescription beanDesc)
        throws JsonMappingException
    {
        JavaType keyType = type.getKeyType();
        JavaType contentType = type.getContentType();
        final DeserializationConfig config = ctxt.getConfig();
        
        // First: is there annotation-specified deserializer for values?
        @SuppressWarnings("unchecked")
        JsonDeserializer<ObjectcontentDeser = (JsonDeserializer<Object>) contentType.getValueHandler();
        
        // Ok: need a key deserializer (null indicates 'default' here)
        KeyDeserializer keyDes = (KeyDeserializerkeyType.getValueHandler();
        /* !!! 24-Jan-2012, tatu: NOTE: impls MUST use resolve() to find key deserializer!
        if (keyDes == null) {
            keyDes = p.findKeyDeserializer(config, keyType, property);
        }
        */
        // Then optional type info (1.5); either attached to type, or resolve separately: