Package org.springframework.batch.item.file.mapping

# Class BeanWrapperFieldSetMapper<T>

java.lang.Object
org.springframework.batch.support.DefaultPropertyEditorRegistrar
org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper<T>

All Implemented Interfaces:
  `FieldSetMapper<T>`, `org.springframework.beans.factory.Aware`, `org.springframework.beans.factory.BeanFactoryAware`, `org.springframework.beans.factory.InitializingBean`, `org.springframework.beans.PropertyEditorRegistrar`

public class BeanWrapperFieldSetMapper<T> extends DefaultPropertyEditorRegistrar implements FieldSetMapper<T>, org.springframework.beans.factory.BeanFactoryAware, org.springframework.beans.factory.InitializingBean
`FieldSetMapper` implementation based on bean property paths. The `FieldSet` to be mapped should have field name meta data corresponding to bean property paths in an instance of the desired type. The instance is created and initialized either by referring to a prototype object by bean name in the enclosing BeanFactory, or by providing a class to instantiate reflectively.
Nested property paths, including indexed properties in maps and collections, can be referenced by the `FieldSet` names. They will be converted to nested bean properties inside the prototype. The `FieldSet` and the prototype are thus tightly coupled by the fields that are available and those that can be initialized. If some of the nested properties are optional (e.g. collection members) they need to be removed by a post processor.
To customize the way that `FieldSet` values are converted to the desired type for injecting into the prototype there are several choices. You can inject `PropertyEditor` instances directly through the `customEditors` property, or you can override the `createBinder(Object)` and `initBinder(DataBinder)` methods, or you can provide a custom `FieldSet` implementation. You can also use a `ConversionService` to convert to the desired type through the `conversionService` property.
Property name matching is "fuzzy" in the sense that it tolerates close matches, as long as the match is unique. For instance:

- Quantity = quantity (field names can be capitalised)
- ISIN = isin (acronyms can be lower case bean property names, as per Java Beans recommendations)
- DuckPate = duckPate (capitalisation including camel casing)
- ITEM_ID = itemId (capitalisation and replacing word boundary with underscore)
- ORDER.CUSTOMER_ID = order.customerId (nested paths are recursively checked)

The algorithm used to match a property name is to start with an exact match and then search successively through more distant matches until precisely one match is found. If more than one match is found there will be an error.

Author:
  Dave Syer, Mahmoud Ben Hassine

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `BeanWrapperFieldSetMapper()`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `void`
  `afterPropertiesSet()`
  Check that precisely one of type or prototype bean name is specified.
  `protected org.springframework.validation.DataBinder`
  `createBinder(Object target)`
  Create a binder for the target object.
  `protected void`
  `initBinder(org.springframework.validation.DataBinder binder)`
  Initialize a new binder instance.
  `T`
  `mapFieldSet(FieldSet fs)`
  Map the `FieldSet` to an object retrieved from the enclosing Spring context, or to a new instance of the required type if no prototype is available.
  `void`
  `setBeanFactory(org.springframework.beans.factory.BeanFactory beanFactory)`
  `void`
  `setConversionService(org.springframework.core.convert.ConversionService conversionService)`
  Public setter for the 'conversionService' property.
  `void`
  `setCustomEditors(Map<? extends Object,? extends PropertyEditor> customEditors)`
  Specify the `custom editors` to register.
  `void`
  `setDistanceLimit(int distanceLimit)`
  The maximum difference that can be tolerated in spelling between input key names and bean property names.
  `void`
  `setPrototypeBeanName(String name)`
  The bean name (id) for an object that can be populated from the field set that will be passed into `mapFieldSet(FieldSet)`.
  `void`
  `setStrict(boolean strict)`
  Public setter for the 'strict' property.
  `void`
  `setTargetType(Class<? extends T> type)`
  Public setter for the type of bean to create instead of using a prototype bean.

  ### Methods inherited from class org.springframework.batch.support.DefaultPropertyEditorRegistrar

  `registerCustomEditors`

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Constructor Details

  - ### BeanWrapperFieldSetMapper

    public BeanWrapperFieldSetMapper()

- ## Method Details

  - ### setBeanFactory

    public void setBeanFactory(org.springframework.beans.factory.BeanFactory beanFactory)
    Specified by:
      `setBeanFactory` in interface `org.springframework.beans.factory.BeanFactoryAware`

  - ### setDistanceLimit

    public void setDistanceLimit(int distanceLimit)
    The maximum difference that can be tolerated in spelling between input key names and bean property names. Defaults to 5, but could be set lower if the field names match the bean names.
    Parameters:
      `distanceLimit` - the distance limit to set

  - ### setPrototypeBeanName

    public void setPrototypeBeanName(String name)
    The bean name (id) for an object that can be populated from the field set that will be passed into `mapFieldSet(FieldSet)`. Typically a prototype scoped bean so that a new instance is returned for each field set mapped. Either this property or the type property must be specified, but not both.
    Parameters:
      `name` - the name of a prototype bean in the enclosing BeanFactory

  - ### setTargetType

    public void setTargetType(Class<? extends T> type)
    Public setter for the type of bean to create instead of using a prototype bean. An object of this type will be created from its default constructor for every call to `mapFieldSet(FieldSet)`.
    Either this property or the prototype bean name must be specified, but not both.
    Parameters:
      `type` - the type to set

  - ### afterPropertiesSet

    public void afterPropertiesSet() throws Exception
    Check that precisely one of type or prototype bean name is specified.
    Specified by:
      `afterPropertiesSet` in interface `org.springframework.beans.factory.InitializingBean`
    Throws:
      `IllegalStateException` - if neither is set or both properties are set.
      `Exception`
    See Also:
      - `InitializingBean.afterPropertiesSet()`

  - ### mapFieldSet

    public T mapFieldSet(FieldSet fs) throws org.springframework.validation.BindException
    Map the `FieldSet` to an object retrieved from the enclosing Spring context, or to a new instance of the required type if no prototype is available.
    Specified by:
      `mapFieldSet` in interface `FieldSetMapper<T>`
    Parameters:
      `fs` - the `FieldSet` to map
    Returns:
      the populated object
    Throws:
      `org.springframework.validation.BindException` - if there is a type conversion or other error (if the `DataBinder` from `createBinder(Object)` has errors after binding).
      `org.springframework.beans.NotWritablePropertyException` - if the `FieldSet` contains a field that cannot be mapped to a bean property.
    See Also:
      - `FieldSetMapper.mapFieldSet(FieldSet)`

  - ### createBinder

    protected org.springframework.validation.DataBinder createBinder(Object target)
    Create a binder for the target object. The binder will then be used to bind the properties form a field set into the target object. This implementation creates a new `DataBinder` and calls out to `initBinder(DataBinder)` and `DefaultPropertyEditorRegistrar.registerCustomEditors(PropertyEditorRegistry)`.
    Parameters:
      `target` - Object to bind to
    Returns:
      a `DataBinder` that can be used to bind properties to the target.

  - ### initBinder

    protected void initBinder(org.springframework.validation.DataBinder binder)
    Initialize a new binder instance. This hook allows customization of binder settings such as the `direct field access`. Called by `createBinder(Object)`.

    Note that registration of custom property editors can be done in `DefaultPropertyEditorRegistrar.registerCustomEditors(PropertyEditorRegistry)`.

    Parameters:
      `binder` - new binder instance
    See Also:
      - `createBinder(Object)`

  - ### setStrict

    public void setStrict(boolean strict)
    Public setter for the 'strict' property. If true, then `mapFieldSet(FieldSet)` will fail of the FieldSet contains fields that cannot be mapped to the bean.
    Parameters:
      `strict` - indicator

  - ### setConversionService

    public void setConversionService(org.springframework.core.convert.ConversionService conversionService)
    Public setter for the 'conversionService' property. `createBinder(Object)` will use it if not null.
    Parameters:
      `conversionService` - `ConversionService` to be used for type conversions

  - ### setCustomEditors

    public void setCustomEditors(Map<? extends Object,? extends PropertyEditor> customEditors)
    Specify the `custom editors` to register.
    Overrides:
      `setCustomEditors` in class `DefaultPropertyEditorRegistrar`
    Parameters:
      `customEditors` - a map of Class to PropertyEditor (or class name to PropertyEditor).
    See Also:
      - `CustomEditorConfigurer.setCustomEditors(Map)`