/**
   * Method called by {@link BeanDeserializerFactory} to see if there might be a standard
   * deserializer registered for given type.
   */
  @SuppressWarnings("unchecked")
  protected JsonDeserializer<Object> findStdDeserializer(
      DeserializationConfig config, JavaType type) throws JsonMappingException {
    Class<?> cls = type.getRawClass();
    // note: we do NOT check for custom deserializers here; that's for sub-class to do
    JsonDeserializer<Object> deser = _simpleDeserializers.get(new ClassKey(cls));
    if (deser != null) {
      return deser;
    }

    // [JACKSON-283]: AtomicReference is a rather special type...
    if (AtomicReference.class.isAssignableFrom(cls)) {
      // Must find parameterization
      TypeFactory tf = config.getTypeFactory();
      JavaType[] params = tf.findTypeParameters(type, AtomicReference.class);
      JavaType referencedType;
      if (params == null || params.length < 1) { // untyped (raw)
        referencedType = TypeFactory.unknownType();
      } else {
        referencedType = params[0];
      }

      JsonDeserializer<?> d2 = new JdkDeserializers.AtomicReferenceDeserializer(referencedType);
      return (JsonDeserializer<Object>) d2;
    }
    // [JACKSON-386]: External/optional type handlers are handled somewhat differently
    JsonDeserializer<?> d = optionalHandlers.findDeserializer(type, config);
    if (d != null) {
      return (JsonDeserializer<Object>) d;
    }
    return null;
  }
 /**
  * Helper method that will check whether given raw type is marked as always ignorable (for purpose
  * of ignoring properties with type)
  */
 protected boolean isIgnorableType(
     DeserializationConfig config,
     BeanDescription beanDesc,
     Class<?> type,
     Map<Class<?>, Boolean> ignoredTypes) {
   Boolean status = ignoredTypes.get(type);
   if (status == null) {
     BeanDescription desc = config.introspectClassAnnotations(type);
     status = config.getAnnotationIntrospector().isIgnorableType(desc.getClassInfo());
     // We default to 'false', ie. not ignorable
     if (status == null) {
       status = Boolean.FALSE;
     }
   }
   return status;
 }
  /**
   * Method for constructing a bean deserializer that uses specified intermediate Builder for
   * binding data, and construction of the value instance. Note that implementation is mostly copied
   * from the regular BeanDeserializer build method.
   */
  @SuppressWarnings("unchecked")
  protected JsonDeserializer<Object> buildBuilderBasedDeserializer(
      DeserializationContext ctxt, JavaType valueType, BeanDescription builderDesc)
      throws JsonMappingException {
    // Creators, anyone? (to create builder itself)
    ValueInstantiator valueInstantiator = findValueInstantiator(ctxt, builderDesc);
    final DeserializationConfig config = ctxt.getConfig();
    BeanDeserializerBuilder builder = constructBeanDeserializerBuilder(ctxt, builderDesc);
    builder.setValueInstantiator(valueInstantiator);
    // And then "with methods" for deserializing from JSON Object
    addBeanProps(ctxt, builderDesc, builder);
    addObjectIdReader(ctxt, builderDesc, builder);

    // managed/back reference fields/setters need special handling... first part
    addReferenceProperties(ctxt, builderDesc, builder);
    addInjectables(ctxt, builderDesc, builder);

    JsonPOJOBuilder.Value builderConfig = builderDesc.findPOJOBuilderConfig();
    final String buildMethodName =
        (builderConfig == null) ? "build" : builderConfig.buildMethodName;

    // and lastly, find build method to use:
    AnnotatedMethod buildMethod = builderDesc.findMethod(buildMethodName, null);
    if (buildMethod != null) { // note: can't yet throw error; may be given build method
      if (config.canOverrideAccessModifiers()) {
        ClassUtil.checkAndFixAccess(buildMethod.getMember());
      }
    }
    builder.setPOJOBuilder(buildMethod, builderConfig);
    // this may give us more information...
    if (_factoryConfig.hasDeserializerModifiers()) {
      for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
        builder = mod.updateBuilder(config, builderDesc, builder);
      }
    }
    JsonDeserializer<?> deserializer = builder.buildBuilderBased(valueType, buildMethodName);

    // [JACKSON-440]: may have modifier(s) that wants to modify or replace serializer we just built:
    if (_factoryConfig.hasDeserializerModifiers()) {
      for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
        deserializer = mod.modifyDeserializer(config, builderDesc, deserializer);
      }
    }
    return (JsonDeserializer<Object>) deserializer;
  }
  /**
   * Method that {@link DeserializerCache}s call to create a new deserializer for types other than
   * Collections, Maps, arrays and enums.
   */
  @Override
  public JsonDeserializer<Object> createBeanDeserializer(
      DeserializationContext ctxt, JavaType type, BeanDescription beanDesc)
      throws JsonMappingException {
    final DeserializationConfig config = ctxt.getConfig();
    // We may also have custom overrides:
    JsonDeserializer<Object> custom = _findCustomBeanDeserializer(type, config, beanDesc);
    if (custom != null) {
      return custom;
    }
    /* One more thing to check: do we have an exception type
     * (Throwable or its sub-classes)? If so, need slightly
     * different handling.
     */
    if (type.isThrowable()) {
      return buildThrowableDeserializer(ctxt, type, beanDesc);
    }
    /* Or, for abstract types, may have alternate means for resolution
     * (defaulting, materialization)
     */
    if (type.isAbstract()) {
      // [JACKSON-41] (v1.6): Let's make it possible to materialize abstract types.
      JavaType concreteType = materializeAbstractType(config, beanDesc);
      if (concreteType != null) {
        /* important: introspect actual implementation (abstract class or
         * interface doesn't have constructors, for one)
         */
        beanDesc = config.introspect(concreteType);
        return buildBeanDeserializer(ctxt, concreteType, beanDesc);
      }
    }

    // Otherwise, may want to check handlers for standard types, from superclass:
    JsonDeserializer<Object> deser = findStdDeserializer(config, type);
    if (deser != null) {
      return deser;
    }

    // Otherwise: could the class be a Bean class? If not, bail out
    if (!isPotentialBeanType(type.getRawClass())) {
      return null;
    }
    // Use generic bean introspection to build deserializer
    return buildBeanDeserializer(ctxt, type, beanDesc);
  }