@SuppressWarnings("deprecation")
 @Override
 public LinkedHashMap<String, AnnotatedMethod> findSetters(
     VisibilityChecker<?> visibilityChecker) {
   LinkedHashMap<String, AnnotatedMethod> results = new LinkedHashMap<String, AnnotatedMethod>();
   for (BeanPropertyDefinition property : _properties) {
     AnnotatedMethod m = property.getSetter();
     if (m != null) {
       results.put(property.getName(), m);
     }
   }
   return results;
 }
  /**
   * Method that will construct a regular bean property setter using the given setter method.
   *
   * @return Property constructed, if any; or null to indicate that there should be no property
   *     based on given definitions.
   */
  protected SettableBeanProperty constructSettableProperty(
      DeserializationContext ctxt,
      BeanDescription beanDesc,
      BeanPropertyDefinition propDef,
      Type jdkType)
      throws JsonMappingException {
    // need to ensure method is callable (for non-public)
    AnnotatedMember mutator = propDef.getMutator();
    if (ctxt.canOverrideAccessModifiers()) {
      mutator.fixAccess();
    }
    // note: this works since we know there's exactly one argument for methods
    JavaType t0 = beanDesc.resolveType(jdkType);

    BeanProperty.Std property =
        new BeanProperty.Std(propDef.getName(), t0, beanDesc.getClassAnnotations(), mutator);
    JavaType type = resolveType(ctxt, beanDesc, t0, mutator);
    // did type change?
    if (type != t0) {
      property = property.withType(type);
    }

    /* First: does the Method specify the deserializer to use?
     * If so, let's use it.
     */
    JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(ctxt, mutator);
    type = modifyTypeByAnnotation(ctxt, mutator, type);
    TypeDeserializer typeDeser = type.getTypeHandler();
    SettableBeanProperty prop;
    if (mutator instanceof AnnotatedMethod) {
      prop =
          new MethodProperty(
              propDef, type, typeDeser, beanDesc.getClassAnnotations(), (AnnotatedMethod) mutator);
    } else {
      prop =
          new FieldProperty(
              propDef, type, typeDeser, beanDesc.getClassAnnotations(), (AnnotatedField) mutator);
    }
    if (propDeser != null) {
      prop = prop.withValueDeserializer(propDeser);
    }
    // [JACKSON-235]: need to retain name of managed forward references:
    AnnotationIntrospector.ReferenceProperty ref = propDef.findReferenceType();
    if (ref != null && ref.isManagedReference()) {
      prop.setManagedReferenceName(ref.getName());
    }
    return prop;
  }
  /** Method that will construct a regular bean property setter using the given setter method. */
  protected SettableBeanProperty constructSetterlessProperty(
      DeserializationContext ctxt, BeanDescription beanDesc, BeanPropertyDefinition propDef)
      throws JsonMappingException {
    final AnnotatedMethod getter = propDef.getGetter();
    // need to ensure it is callable now:
    if (ctxt.canOverrideAccessModifiers()) {
      getter.fixAccess();
    }

    /* 26-Jan-2012, tatu: Alas, this complication is still needed to handle
     *   (or at least work around) local type declarations...
     */
    JavaType type = getter.getType(beanDesc.bindingsForBeanType());
    /* First: does the Method specify the deserializer to use?
     * If so, let's use it.
     */
    JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(ctxt, getter);
    type = modifyTypeByAnnotation(ctxt, getter, type);
    TypeDeserializer typeDeser = type.getTypeHandler();
    SettableBeanProperty prop =
        new SetterlessProperty(propDef, type, typeDeser, beanDesc.getClassAnnotations(), getter);
    if (propDeser != null) {
      prop = prop.withValueDeserializer(propDeser);
    }
    return prop;
  }
 /**
  * @param ignoredProperties (optional) names of properties to ignore; any fields that would be
  *     recognized as one of these properties is ignored.
  * @param forSerialization If true, will collect serializable property fields; if false,
  *     deserializable
  * @return Ordered Map with logical property name as key, and matching field as value.
  */
 public LinkedHashMap<String, AnnotatedField> _findPropertyFields(
     Collection<String> ignoredProperties, boolean forSerialization) {
   LinkedHashMap<String, AnnotatedField> results = new LinkedHashMap<String, AnnotatedField>();
   for (BeanPropertyDefinition property : _properties) {
     AnnotatedField f = property.getField();
     if (f != null) {
       String name = property.getName();
       if (ignoredProperties != null) {
         if (ignoredProperties.contains(name)) {
           continue;
         }
       }
       results.put(name, f);
     }
   }
   return results;
 }
 @SuppressWarnings("deprecation")
 @Override
 public LinkedHashMap<String, AnnotatedMethod> findGetters(
     VisibilityChecker<?> visibilityChecker, Collection<String> ignoredProperties) {
   LinkedHashMap<String, AnnotatedMethod> results = new LinkedHashMap<String, AnnotatedMethod>();
   for (BeanPropertyDefinition property : _properties) {
     AnnotatedMethod m = property.getGetter();
     if (m != null) {
       String name = property.getName();
       if (ignoredProperties != null) {
         if (ignoredProperties.contains(name)) {
           continue;
         }
       }
       results.put(name, m);
     }
   }
   return results;
 }
 /**
  * Method for locating all back-reference properties (setters, fields) bean has
  *
  * @since 1.6
  */
 public Map<String, AnnotatedMember> findBackReferenceProperties() {
   HashMap<String, AnnotatedMember> result = null;
   for (BeanPropertyDefinition property : _properties) {
     AnnotatedMember am = property.getMutator();
     if (am == null) {
       continue;
     }
     AnnotationIntrospector.ReferenceProperty refDef =
         _annotationIntrospector.findReferenceType(am);
     if (refDef != null && refDef.isBackReference()) {
       if (result == null) {
         result = new HashMap<String, AnnotatedMember>();
       }
       String refName = refDef.getName();
       if (result.put(refName, am) != null) {
         throw new IllegalArgumentException(
             "Multiple back-reference properties with name '" + refName + "'");
       }
     }
   }
   return result;
 }
  /**
   * Helper method called to filter out explicit ignored properties, as well as properties that have
   * "ignorable types". Note that this will not remove properties that have no setters.
   */
  protected List<BeanPropertyDefinition> filterBeanProps(
      DeserializationContext ctxt,
      BeanDescription beanDesc,
      BeanDeserializerBuilder builder,
      List<BeanPropertyDefinition> propDefsIn,
      Set<String> ignored)
      throws JsonMappingException {
    ArrayList<BeanPropertyDefinition> result =
        new ArrayList<BeanPropertyDefinition>(Math.max(4, propDefsIn.size()));
    HashMap<Class<?>, Boolean> ignoredTypes = new HashMap<Class<?>, Boolean>();
    // These are all valid setters, but we do need to introspect bit more
    for (BeanPropertyDefinition property : propDefsIn) {
      String name = property.getName();
      if (ignored.contains(
          name)) { // explicit ignoral using @JsonIgnoreProperties needs to block entries
        continue;
      }
      if (!property.hasConstructorParameter()) { // never skip constructor params
        Class<?> rawPropertyType = null;
        if (property.hasSetter()) {
          rawPropertyType = property.getSetter().getRawParameterType(0);
        } else if (property.hasField()) {
          rawPropertyType = property.getField().getRawType();
        }

        // [JACKSON-429] Some types are declared as ignorable as well
        if ((rawPropertyType != null)
            && (isIgnorableType(ctxt.getConfig(), beanDesc, rawPropertyType, ignoredTypes))) {
          // important: make ignorable, to avoid errors if value is actually seen
          builder.addIgnorable(name);
          continue;
        }
      }
      result.add(property);
    }
    return result;
  }
  /**
   * Method called to figure out settable properties for the bean deserializer to use.
   *
   * <p>Note: designed to be overridable, and effort is made to keep interface similar between
   * versions.
   */
  protected void addBeanProps(
      DeserializationContext ctxt, BeanDescription beanDesc, BeanDeserializerBuilder builder)
      throws JsonMappingException {
    final SettableBeanProperty[] creatorProps =
        builder.getValueInstantiator().getFromObjectArguments(ctxt.getConfig());

    // Things specified as "ok to ignore"? [JACKSON-77]
    AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
    boolean ignoreAny = false;
    {
      Boolean B = intr.findIgnoreUnknownProperties(beanDesc.getClassInfo());
      if (B != null) {
        ignoreAny = B.booleanValue();
        builder.setIgnoreUnknownProperties(ignoreAny);
      }
    }
    // Or explicit/implicit definitions?
    Set<String> ignored =
        ArrayBuilders.arrayToSet(intr.findPropertiesToIgnore(beanDesc.getClassInfo()));
    for (String propName : ignored) {
      builder.addIgnorable(propName);
    }
    // Also, do we have a fallback "any" setter?
    AnnotatedMethod anySetter = beanDesc.findAnySetter();
    if (anySetter != null) {
      builder.setAnySetter(constructAnySetter(ctxt, beanDesc, anySetter));
    }
    // NOTE: we do NOT add @JsonIgnore'd properties into blocked ones if there's any setter
    // Implicit ones via @JsonIgnore and equivalent?
    if (anySetter == null) {
      Collection<String> ignored2 = beanDesc.getIgnoredPropertyNames();
      if (ignored2 != null) {
        for (String propName : ignored2) {
          // allow ignoral of similarly named JSON property, but do not force;
          // latter means NOT adding this to 'ignored':
          builder.addIgnorable(propName);
        }
      }
    }
    final boolean useGettersAsSetters =
        (ctxt.isEnabled(MapperFeature.USE_GETTERS_AS_SETTERS)
            && ctxt.isEnabled(MapperFeature.AUTO_DETECT_GETTERS));

    // Ok: let's then filter out property definitions
    List<BeanPropertyDefinition> propDefs =
        filterBeanProps(ctxt, beanDesc, builder, beanDesc.findProperties(), ignored);

    // After which we can let custom code change the set
    if (_factoryConfig.hasDeserializerModifiers()) {
      for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
        propDefs = mod.updateProperties(ctxt.getConfig(), beanDesc, propDefs);
      }
    }

    // At which point we still have all kinds of properties; not all with mutators:
    for (BeanPropertyDefinition propDef : propDefs) {
      SettableBeanProperty prop = null;
      if (propDef.hasConstructorParameter()) {
        /* [JACKSON-700] If property is passed via constructor parameter, we must
         *   handle things in special way. Not sure what is the most optimal way...
         *   for now, let's just call a (new) method in builder, which does nothing.
         */
        // but let's call a method just to allow custom builders to be aware...
        final String name = propDef.getName();
        for (SettableBeanProperty cp : creatorProps) {
          if (name.equals(cp.getName())) {
            prop = cp;
            break;
          }
        }
        if (prop == null) {
          throw ctxt.mappingException("Could not find creator property with name '" + name + "'");
        }
        builder.addCreatorProperty(prop);
        continue;
      }
      if (propDef.hasSetter()) {
        Type propertyType = propDef.getSetter().getGenericParameterType(0);
        prop = constructSettableProperty(ctxt, beanDesc, propDef, propertyType);
      } else if (propDef.hasField()) {
        Type propertyType = propDef.getField().getGenericType();
        prop = constructSettableProperty(ctxt, beanDesc, propDef, propertyType);
      } else if (useGettersAsSetters && propDef.hasGetter()) {
        /* As per [JACKSON-88], may also need to consider getters
         * for Map/Collection properties; but with lowest precedence
         */
        AnnotatedMethod getter = propDef.getGetter();
        // should only consider Collections and Maps, for now?
        Class<?> rawPropertyType = getter.getRawType();
        if (Collection.class.isAssignableFrom(rawPropertyType)
            || Map.class.isAssignableFrom(rawPropertyType)) {
          prop = constructSetterlessProperty(ctxt, beanDesc, propDef);
        }
      }
      if (prop != null) {
        Class<?>[] views = propDef.findViews();
        if (views == null) {
          // one more twist: if default inclusion disabled, need to force empty set of views
          if (!ctxt.isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION)) {
            views = NO_VIEWS;
          }
        }
        // one more thing before adding to builder: copy any metadata
        prop.setViews(views);
        builder.addProperty(prop);
      }
    }
  }
 private void _verifyProperty(BeanDescription beanDesc, boolean verifyDesc, boolean verifyIndex) {
   assertNotNull(beanDesc);
   List<BeanPropertyDefinition> props = beanDesc.findProperties();
   assertEquals(2, props.size());
   for (BeanPropertyDefinition prop : props) {
     String name = prop.getName();
     final PropertyMetadata md = prop.getMetadata();
     if ("a".equals(name)) {
       assertFalse(md.isRequired());
       assertNull(md.getRequired());
       if (verifyDesc) {
         assertEquals(PropDescBean.A_DESC, md.getDescription());
       }
       if (verifyIndex) {
         assertNull(md.getIndex());
       }
     } else if ("b".equals(name)) {
       assertTrue(md.isRequired());
       assertEquals(Boolean.TRUE, md.getRequired());
       if (verifyDesc) {
         assertNull(md.getDescription());
       }
       if (verifyIndex) {
         assertEquals(Integer.valueOf(PropDescBean.B_INDEX), md.getIndex());
       }
     } else {
       fail("Unrecognized property '" + name + "'");
     }
   }
 }