/**
   * 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);
  }
  /**
   * Method that is to actually build a bean deserializer instance. All basic sanity checks have
   * been done to know that what we have may be a valid bean type, and that there are no default
   * simple deserializers.
   */
  @SuppressWarnings("unchecked")
  public JsonDeserializer<Object> buildBeanDeserializer(
      DeserializationContext ctxt, JavaType type, BeanDescription beanDesc)
      throws JsonMappingException {
    // First: check what creators we can use, if any
    ValueInstantiator valueInstantiator = findValueInstantiator(ctxt, beanDesc);
    BeanDeserializerBuilder builder = constructBeanDeserializerBuilder(ctxt, beanDesc);
    builder.setValueInstantiator(valueInstantiator);
    // And then setters for deserializing from JSON Object
    addBeanProps(ctxt, beanDesc, builder);
    addObjectIdReader(ctxt, beanDesc, builder);

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

    final DeserializationConfig config = ctxt.getConfig();
    // [JACKSON-440]: update builder now that all information is in?
    if (_factoryConfig.hasDeserializerModifiers()) {
      for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
        builder = mod.updateBuilder(config, beanDesc, builder);
      }
    }
    JsonDeserializer<?> deserializer;

    /* 19-Mar-2012, tatu: This check used to be done earlier; but we have to defer
     *   it a bit to collect information on ObjectIdReader, for example.
     */
    if (type.isAbstract() && !valueInstantiator.canInstantiate()) {
      deserializer = builder.buildAbstract();
    } else {
      deserializer = builder.build();
    }

    // [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, beanDesc, deserializer);
      }
    }
    return (JsonDeserializer<Object>) deserializer;
  }