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" commmon 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.

  
  public abstract class BasicDeserializerFactory
      extends DeserializerFactory
      implements java.io.Serializable
  {
      private static final long serialVersionUID = 1;

    
We will pre-create serializers for common non-structured (that is things other than Collection, Map or array) types. These need not go through factory.
  
      final protected static HashMap<ClassKeyJsonDeserializer<Object>> _simpleDeserializers
          = new HashMap<ClassKeyJsonDeserializer<Object>>();

    
Also special array deserializers for primitive array types.
  
      final protected static HashMap<JavaType,JsonDeserializer<Object>> _arrayDeserializers
          = PrimitiveArrayDeserializers.getAll();

    
Set of available key deserializers is currently limited to standard types; and all known instances are storing in this map.
  
      final protected static HashMap<JavaTypeKeyDeserializer_keyDeserializers = StdKeyDeserializers.constructAll();
  
      static {
          // First, add the fall-back "untyped" deserializer:
          _add(Object.classnew UntypedObjectDeserializer());
      
          // Then String and String-like converters:
          StdDeserializer<?> strDeser = new StringDeserializer();
          _add(String.classstrDeser);
          _add(CharSequence.classstrDeser);
      
          // Primitives/wrappers, other Numbers:
          _add(, NumberDeserializers.all());
          // Date/time types
          _add(, DateDeserializers.all());
          // other JDK types
          _add(, JdkDeserializers.all());
          // and a few Jackson types as well:
          _add(, JacksonDeserializers.all());
      }
  
      private static void _add(Map<ClassKeyJsonDeserializer<Object>> desers,
              StdDeserializer<?>[] serializers) {
          for (StdDeserializer<?> ser : serializers) {
              _add(desersser.getValueClass(), ser);
          }
      }
  
      private static void _add(Map<ClassKeyJsonDeserializer<Object>> desers,
              Class<?> valueClassStdDeserializer<?> stdDeser)
      {
          @SuppressWarnings("unchecked")
          JsonDeserializer<Objectdeser = (JsonDeserializer<Object>) stdDeser;
          desers.put(new ClassKey(valueClass), deser);
      }
      
      /* 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 = Class.forName("java.util.concurrent.ConcurrentNavigableMap");
             Class<?> value = Class.forName("java.util.concurrent.ConcurrentSkipListMap");
             @SuppressWarnings("unchecked")
                 Class<? extends Map<?,?>> mapValue = (Class<? extends Map<?,?>>) value;
             .put(key.getName(), mapValue);
         } catch (ClassNotFoundException cnfe) { // occurs on 1.5
         } catch (SecurityException se) { // might occur in applets, see stackoverflow.com/questions/12345068
         }
     }
 
     /* 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);
 
         /* 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.Deque"LinkedList.class);
         .put("java.util.NavigableSet"TreeSet.class);
     }

    
To support external/optional deserializers, we'll use a helper 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");
                 }
             }
         }
         
         return instantiator;
     }
 
             BeanDescription beanDesc)
         throws JsonMappingException
     {
         return JacksonDeserializers.findValueInstantiator(configbeanDesc);
     }

    
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) {
             inst = (ValueInstantiatorinstDef;
         } else {
             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);
             } else {
                 inst = (ValueInstantiator) ClassUtil.createInstance(instClass,
                         config.canOverrideAccessModifiers());
             }
         }
         // not resolvable or contextual, just return:
         return inst;
     }
     
     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);
             }
         }
         
         for (AnnotatedConstructor ctor : beanDesc.getConstructors()) {
             int argCount = ctor.getParameterCount();
             boolean isCreator = intr.hasCreatorAnnotation(ctor);
             boolean isVisible =  vchecker.isCreatorVisible(ctor);
             // some single-arg constructors (String, number) are auto-detected
             if (argCount == 1) {
                 _handleSingleArgumentConstructor(ctxtbeanDescvcheckerintrcreators,
                         ctorisCreatorisVisible);
                 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 pn = (param == null) ? null : intr.findNameForDeserialization(param);
                 String name = (pn == null) ? null : pn.getSimpleName();
                 Object injectId = intr.findInjectableValueId(param);
                 if (name != null && name.length() > 0) {
                     ++namedCount;
                     properties[i] = constructCreatorProperty(ctxtbeanDescnameiparaminjectId);
                 } else if (injectId != null) {
                     ++injectCount;
                     properties[i] = constructCreatorProperty(ctxtbeanDescnameiparaminjectId);
                 } 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, epic fail
                     throw new IllegalArgumentException("Argument #"+nonAnnotatedParam.getIndex()+" of constructor "+ctor+" has no property name annotation; must have name when multiple-paramater constructor annotated as Creator");
                 }
             }
         }
     }
 
     protected boolean _handleSingleArgumentConstructor(DeserializationContext ctxt,
             BeanDescription beanDescVisibilityChecker<?> vchecker,
             AnnotationIntrospector intrCreatorCollector creators,
             AnnotatedConstructor ctorboolean isCreatorboolean isVisible)
         throws JsonMappingException
     {
         // note: if we do have parameter name, it'll be "property constructor":
         AnnotatedParameter param = ctor.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)) { // 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 pn = (param == null) ? null : intr.findNameForDeserialization(param);
                 String name = (pn == null) ? null : pn.getSimpleName();
                 Object injectId = intr.findInjectableValueId(param);
                 if (name != null && name.length() > 0) {
                     ++namedCount;
                     properties[i] = constructCreatorProperty(ctxtbeanDescnameiparaminjectId);
                 } else if (injectId != null) {
                     ++injectCount;
                     properties[i] = constructCreatorProperty(ctxtbeanDescnameiparaminjectId);
                 } 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 beanDescString nameint index,
             AnnotatedParameter param,
             Object injectableValueId)
         throws JsonMappingException
     {
         final DeserializationConfig config = ctxt.getConfig();
         JavaType t0 = config.getTypeFactory().constructType(param.getParameterType(), beanDesc.bindingsForBeanType());
         BeanProperty.Std property = new BeanProperty.Std(namet0beanDesc.getClassAnnotations(), param);
         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(nametypetypeDeser,
                 beanDesc.getClassAnnotations(), paramindexinjectableValueId);
         if (deser != null) {
             prop = prop.withValueDeserializer(deser);
         }
         return prop;
     }
     
     /*
     /**********************************************************
     /* JsonDeserializerFactory impl: array deserializers
     /**********************************************************
      */
         
     @Override
             ArrayType typefinal BeanDescription beanDesc)
         throws JsonMappingException
     {
         JavaType elemType = type.getContentType();
         
         // Very first thing: is deserializer hard-coded for elements?
         JsonDeserializer<ObjectcontentDeser = elemType.getValueHandler();
         if (contentDeser == null) {
             // Maybe special array type, such as "primitive" arrays (int[] etc)
             JsonDeserializer<?> deser = .get(elemType);
             if (deser != null) {
                 /* 23-Nov-2010, tatu: Although not commonly needed, ability to override
                  *   deserializers for all types (including primitive arrays) is useful
                  *   so let's allow this
                  */
                 JsonDeserializer<?> custom = _findCustomArrayDeserializer(type,
                         ctxt.getConfig(), beanDescnullcontentDeser);
                 if (custom != null) {
                     return custom;
                 }
                 return deser;
             }
             // If not, generic one:
             if (elemType.isPrimitive()) { // sanity check
                 throw new IllegalArgumentException("Internal error: primitive type ("+type+") passed, no array deserializer found");
             }
         }
         // 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(ctxt.getConfig(), elemType);
         }
         // 23-Nov-2010, tatu: Custom array deserializer?
         JsonDeserializer<?> custom = _findCustomArrayDeserializer(type,
                 ctxt.getConfig(), beanDescelemTypeDesercontentDeser);
         if (custom != null) {
             return custom;
         }
         return new ObjectArrayDeserializer(typecontentDeserelemTypeDeser);
     }
 
             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();
 
         // 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(ctxt.getConfig(), contentType);
         }
 
         // 23-Nov-2010, tatu: Custom deserializer?
         JsonDeserializer<?> custom = _findCustomCollectionDeserializer(type,
                 ctxt.getConfig(), beanDesccontentTypeDesercontentDeser);
         if (custom != null) {
             return custom;
         }
         
         Class<?> collectionClass = type.getRawClass();
         if (contentDeser == null) { // not defined by annotation
             // One special type: EnumSet:
             if (EnumSet.class.isAssignableFrom(collectionClass)) {
                 return 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 (type.isInterface() || type.isAbstract()) {
             @SuppressWarnings({ "rawtypes" })
             Class<? extends Collectionfallback = .get(collectionClass.getName());
             if (fallback == null) {
                 throw new IllegalArgumentException("Can not find a deserializer for non-concrete Collection type "+type);
             }
             collectionClass = fallback;
             type = (CollectionTypectxt.getConfig().constructSpecializedType(typecollectionClass);
             // But if so, also need to re-check creators...
             beanDesc = ctxt.getConfig().introspectForCreation(type);
         }
         ValueInstantiator inst = findValueInstantiator(ctxtbeanDesc);
         // 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:
             return new StringCollectionDeserializer(typecontentDeserinst);
         }
         return new CollectionDeserializer(typecontentDesercontentTypeDeserinst);
     }
 
     // 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();
 
         // 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(ctxt.getConfig(), contentType);
         }
         return _findCustomCollectionLikeDeserializer(typectxt.getConfig(), beanDesc,
                 contentTypeDesercontentDeser);
     }
   
             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;
     }
 
             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<?> custom = _findCustomMapDeserializer(typeconfigbeanDesc,
                 keyDescontentTypeDesercontentDeser);
 
         if (custom != null) {
             return custom;
         }
         // 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");
             }
             return new EnumMapDeserializer(typenullcontentDeser);
         }
 
         // 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 (type.isInterface() || type.isAbstract()) {
             @SuppressWarnings("rawtypes")
             Class<? extends Mapfallback = .get(mapClass.getName());
             if (fallback == null) {
                 throw new IllegalArgumentException("Can not find a deserializer for non-concrete Map type "+type);
             }
             mapClass = fallback;
             type = (MapTypeconfig.constructSpecializedType(typemapClass);
             // But if so, also need to re-check creators...
             beanDesc = config.introspectForCreation(type);
         }
         ValueInstantiator inst = findValueInstantiator(ctxtbeanDesc);
         MapDeserializer md = new MapDeserializer(typeinstkeyDescontentDesercontentTypeDeser);
         return md;
     }
 
     // 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();
         
         // 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:
         TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
         // but if not, may still be possible to find:
         if (contentTypeDeser == null) {
             contentTypeDeser = findTypeDeserializer(ctxt.getConfig(), contentType);
         }
         return _findCustomMapLikeDeserializer(typectxt.getConfig(),
                 beanDesckeyDescontentTypeDesercontentDeser);
     }
 
             DeserializationConfig configBeanDescription beanDesc,
             KeyDeserializer keyDeserializer,
             TypeDeserializer elementTypeDeserializerJsonDeserializer<?> elementDeserializer)
         throws JsonMappingException
     {
         for (Deserializers d  : .deserializers()) {
             JsonDeserializer<?> deser = d.findMapDeserializer(typeconfigbeanDesc,
                     keyDeserializerelementTypeDeserializerelementDeserializer);
             if (deser != null) {
                 return deser;
             }
         }
         return null;
     }
 
             DeserializationConfig configBeanDescription beanDesc,
             KeyDeserializer keyDeserializer,
             TypeDeserializer elementTypeDeserializerJsonDeserializer<?> elementDeserializer)
         throws JsonMappingException
     {
         for (Deserializers d  : .deserializers()) {
             JsonDeserializer<?> deser = d.findMapLikeDeserializer(typeconfigbeanDesc,
                     keyDeserializerelementTypeDeserializerelementDeserializer);
             if (deser != null) {
                 return deser;
             }
         }
         return null;
    }
    
    /*
    /**********************************************************
    /* JsonDeserializerFactory impl: Enum deserializers
    /**********************************************************
     */
    
    
Factory method for constructing serializers of java.lang.Enum types.
    @Override
            JavaType typeBeanDescription beanDesc)
        throws JsonMappingException
    {
        Class<?> enumClass = type.getRawClass();
        // 23-Nov-2010, tatu: Custom deserializer?
        JsonDeserializer<?> custom = _findCustomEnumDeserializer(enumClass,
                ctxt.getConfig(), beanDesc);
        if (custom != null) {
            return custom;
        }
        // [JACKSON-193] May have @JsonCreator for static factory method:
        for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) {
            if (ctxt.getAnnotationIntrospector().hasCreatorAnnotation(factory)) {
                int argCount = factory.getParameterCount();
                if (argCount == 1) {
                    Class<?> returnType = factory.getRawReturnType();
                    // usually should be class, but may be just plain Enum<?> (for Enum.valueOf()?)
                    if (