/**
   * 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;
  }
  protected DeserializationContext(
      DeserializationContext src,
      DeserializationConfig config,
      JsonParser jp,
      InjectableValues injectableValues) {
    _cache = src._cache;
    _factory = src._factory;

    _config = config;
    _featureFlags = config.getDeserializationFeatures();
    _view = config.getActiveView();
    _parser = jp;
    _injectableValues = injectableValues;
  }
 /**
  * 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 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 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;
  }
  // Test to ensure that we can check property ordering defaults...
  public void testConfigForPropertySorting() throws Exception {
    ObjectMapper m = new ObjectMapper();

    // sort-alphabetically is disabled by default:
    assertFalse(m.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY));
    SerializationConfig sc = m.getSerializationConfig();
    assertFalse(sc.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY));
    assertFalse(sc.shouldSortPropertiesAlphabetically());
    DeserializationConfig dc = m.getDeserializationConfig();
    assertFalse(dc.shouldSortPropertiesAlphabetically());

    // but when enabled, should be visible:
    m.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
    sc = m.getSerializationConfig();
    assertTrue(sc.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY));
    assertTrue(sc.shouldSortPropertiesAlphabetically());
    dc = m.getDeserializationConfig();
    // and not just via SerializationConfig, but also via DeserializationConfig
    assertTrue(dc.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY));
    assertTrue(dc.shouldSortPropertiesAlphabetically());
  }
 protected DateFormat getDateFormat() {
   if (_dateFormat != null) {
     return _dateFormat;
   }
   /* 24-Feb-2012, tatu: At this point, all timezone configuration
    *    should have occured, with respect to default dateformat
    *    and timezone configuration. But we still better clone
    *    an instance as formatters may be stateful.
    */
   DateFormat df = _config.getDateFormat();
   _dateFormat = df = (DateFormat) df.clone();
   return df;
 }
 /**
  * Method deserializers can call to inform configured {@link DeserializationProblemHandler}s of an
  * unrecognized property.
  */
 public boolean handleUnknownProperty(
     JsonParser jp, JsonDeserializer<?> deser, Object instanceOrClass, String propName)
     throws IOException, JsonProcessingException {
   LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
   if (h != null) {
     while (h != null) {
       // Can bail out if it's handled
       if (h.value().handleUnknownProperty(this, jp, deser, instanceOrClass, propName)) {
         return true;
       }
       h = h.next();
     }
   }
   return false;
 }
 @Override
 public List<BeanPropertyDefinition> updateProperties(
     DeserializationConfig config,
     BeanDescription beanDesc,
     List<BeanPropertyDefinition> propDefs) {
   final AnnotationIntrospector intr = config.getAnnotationIntrospector();
   int changed = 0;
   for (int i = 0, len = propDefs.size(); i < len; ++i) {
     BeanPropertyDefinition prop = propDefs.get(i);
     AnnotatedMember acc = prop.getAccessor();
     // should not be null, but just in case:
     if (acc == null) {
       continue;
     }
     // first: do we need to handle wrapping (for Lists)?
     QName wrapperName = AnnotationUtil.findWrapperName(intr, acc);
     if (wrapperName != null) {
       String localName = wrapperName.getLocalPart();
       if ((localName != null && localName.length() >= 0) && !localName.equals(prop.getName())) {
         // make copy-on-write as necessary
         if (changed == 0) {
           propDefs = new ArrayList<BeanPropertyDefinition>(propDefs);
         }
         ++changed;
         propDefs.set(i, prop.withName(localName));
         continue;
       }
     } else {
       /* If not, how about "as text" unwrapping? Such properties
        * are exposed as values of 'unnamed' fields; so one way to
        * map them is to rename property to have name ""... (and
        * hope this does not break other parts...)
        */
       Boolean b = AnnotationUtil.findIsTextAnnotation(intr, acc);
       if (b != null && b.booleanValue()) {
         // unwrapped properties will appear as 'unnamed' (empty String)
         propDefs.set(i, prop.withName(""));
         continue;
       }
     }
   }
   return propDefs;
 }
 /**
  * Method for accessing default TimeZone to use: convenience method for
  *
  * <pre>
  *   getConfig().getTimeZone();
  * </pre>
  */
 public TimeZone getTimeZone() {
   return _config.getTimeZone();
 }
 public final boolean isEnabled(MapperFeature feat) {
   return _config.isEnabled(feat);
 }
 public final AnnotationIntrospector getAnnotationIntrospector() {
   return _config.getAnnotationIntrospector();
 }
 /**
  * Convenience method, functionally equivalent to:
  *
  * <pre>
  *  getConfig().canOverrideAccessModifiers();
  * </pre>
  */
 public final boolean canOverrideAccessModifiers() {
   return _config.canOverrideAccessModifiers();
 }
 /**
  * Convenience method, functionally equivalent to:
  *
  * <pre>
  *  getConfig().constructType(cls);
  * </pre>
  */
 public final JavaType constructType(Class<?> cls) {
   return _config.constructType(cls);
 }
 /**
  * Convenience method for accessing the default Base64 encoding used for decoding base64 encoded
  * binary content. Same as calling:
  *
  * <pre>
  *  getConfig().getBase64Variant();
  * </pre>
  */
 public final Base64Variant getBase64Variant() {
   return _config.getBase64Variant();
 }
 /**
  * Method for accessing default Locale to use: convenience method for
  *
  * <pre>
  *   getConfig().getLocale();
  * </pre>
  */
 public Locale getLocale() {
   return _config.getLocale();
 }
 /**
  * Convenience method, functionally equivalent to:
  *
  * <pre>
  *  getConfig().getTypeFactory();
  * </pre>
  */
 public final TypeFactory getTypeFactory() {
   return _config.getTypeFactory();
 }
 /**
  * Convenience method, functionally equivalent to:
  *
  * <pre>
  *  getConfig().getNodeFactory();
  * </pre>
  */
 public final JsonNodeFactory getNodeFactory() {
   return _config.getNodeFactory();
 }