org.springframework.beans

## Class AbstractNestablePropertyAccessor

- java.lang.Object
- - org.springframework.beans.PropertyEditorRegistrySupport
  - - org.springframework.beans.TypeConverterSupport
    - - org.springframework.beans.AbstractPropertyAccessor
      - - org.springframework.beans.AbstractNestablePropertyAccessor

- All Implemented Interfaces:
    ConfigurablePropertyAccessor, PropertyAccessor, PropertyEditorRegistry, TypeConverter
  Direct Known Subclasses:
    BeanWrapperImpl, DirectFieldAccessor

      public abstract class AbstractNestablePropertyAccessor
      extends AbstractPropertyAccessor

  A basic `ConfigurablePropertyAccessor` that provides the necessary infrastructure for all typical use cases.

  This accessor will convert collection and array values to the corresponding target collections or arrays, if necessary. Custom property editors that deal with collections or arrays can either be written via PropertyEditor's `setValue`, or against a comma-delimited String via `setAsText`, as String arrays are converted in such a format if the array itself is not assignable.

  Since:
    4.2
  Author:
    Juergen Hoeller, Stephane Nicoll, Rod Johnson, Rob Harrop
  See Also:
    `PropertyEditorRegistrySupport.registerCustomEditor(java.lang.Class<?>, java.beans.PropertyEditor)`, `AbstractPropertyAccessor.setPropertyValues(java.util.Map<?, ?>)`, `setPropertyValue(java.lang.String, java.lang.Object)`, `getPropertyValue(java.lang.String)`, `getPropertyType(java.lang.String)`, `BeanWrapper`, `PropertyEditorRegistrySupport`

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class and Description
    --- | ---
    `protected static class` | `AbstractNestablePropertyAccessor.PropertyHandler` A handler for a specific property.
    `protected static class` | `AbstractNestablePropertyAccessor.PropertyTokenHolder` Holder class used to store property tokens.

  - ### Field Summary

    - ### Fields inherited from interface org.springframework.beans.PropertyAccessor

      `NESTED_PROPERTY_SEPARATOR, NESTED_PROPERTY_SEPARATOR_CHAR, PROPERTY_KEY_PREFIX, PROPERTY_KEY_PREFIX_CHAR, PROPERTY_KEY_SUFFIX, PROPERTY_KEY_SUFFIX_CHAR`

  - ### Constructor Summary

    Constructors
    Modifier | Constructor and Description
    --- | ---
    `protected` | `AbstractNestablePropertyAccessor()` Create a new empty accessor.
    `protected` | `AbstractNestablePropertyAccessor(boolean registerDefaultEditors)` Create a new empty accessor.
    `protected` | `AbstractNestablePropertyAccessor(Class<?> clazz)` Create a new accessor, wrapping a new instance of the specified class.
    `protected` | `AbstractNestablePropertyAccessor(Object object)` Create a new accessor for the given object.
    `protected` | `AbstractNestablePropertyAccessor(Object object, String nestedPath, AbstractNestablePropertyAccessor parent)` Create a new accessor for the given object, registering a nested path that the object is in.
    `protected` | `AbstractNestablePropertyAccessor(Object object, String nestedPath, Object rootObject)` Create a new accessor for the given object, registering a nested path that the object is in.

  - ### Method Summary

    All Methods Instance Methods Abstract Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `protected Object` | `convertForProperty(String propertyName, Object oldValue, Object newValue, TypeDescriptor td)`
    `protected abstract NotWritablePropertyException` | `createNotWritablePropertyException(String propertyName)` Create a `NotWritablePropertyException` for the specified property.
    `int` | `getAutoGrowCollectionLimit()` Return the limit for array and collection auto-growing.
    `protected String` | `getFinalPath(AbstractNestablePropertyAccessor pa, String nestedPath)` Get the last component of the path.
    `protected abstract AbstractNestablePropertyAccessor.PropertyHandler` | `getLocalPropertyHandler(String propertyName)` Return a `AbstractNestablePropertyAccessor.PropertyHandler` for the specified local `propertyName`.
    `String` | `getNestedPath()` Return the nested path of the object wrapped by this accessor.
    `protected AbstractNestablePropertyAccessor` | `getPropertyAccessorForPropertyPath(String propertyPath)` Recursively navigate to return a property accessor for the nested property path.
    `protected AbstractNestablePropertyAccessor.PropertyHandler` | `getPropertyHandler(String propertyName)` Return the `AbstractNestablePropertyAccessor.PropertyHandler` for the specified `propertyName`, navigating if necessary.
    `Class<?>` | `getPropertyType(String propertyName)` Determine the property type for the given property path.
    `TypeDescriptor` | `getPropertyTypeDescriptor(String propertyName)` Return a type descriptor for the specified property: preferably from the read method, falling back to the write method.
    `protected Object` | `getPropertyValue(AbstractNestablePropertyAccessor.PropertyTokenHolder tokens)`
    `Object` | `getPropertyValue(String propertyName)` Actually get the value of a property.
    `Class<?>` | `getRootClass()` Return the class of the root object at the top of the path of this accessor.
    `Object` | `getRootInstance()` Return the root object at the top of the path of this accessor.
    `Class<?>` | `getWrappedClass()`
    `Object` | `getWrappedInstance()`
    `boolean` | `isReadableProperty(String propertyName)` Determine whether the specified property is readable.
    `boolean` | `isWritableProperty(String propertyName)` Determine whether the specified property is writable.
    `protected abstract AbstractNestablePropertyAccessor` | `newNestedPropertyAccessor(Object object, String nestedPath)` Create a new nested property accessor instance.
    `void` | `setAutoGrowCollectionLimit(int autoGrowCollectionLimit)` Specify a limit for array and collection auto-growing.
    `protected void` | `setPropertyValue(AbstractNestablePropertyAccessor.PropertyTokenHolder tokens, PropertyValue pv)`
    `void` | `setPropertyValue(PropertyValue pv)` Set the specified value as current property value.
    `void` | `setPropertyValue(String propertyName, Object value)` Actually set a property value.
    `void` | `setWrappedInstance(Object object)` Switch the target object, replacing the cached introspection results only if the class of the new object is different to that of the replaced object.
    `void` | `setWrappedInstance(Object object, String nestedPath, Object rootObject)` Switch the target object, replacing the cached introspection results only if the class of the new object is different to that of the replaced object.
    `String` | `toString()`

    - ### Methods inherited from class org.springframework.beans.AbstractPropertyAccessor

      `isAutoGrowNestedPaths, isExtractOldValueForEditor, setAutoGrowNestedPaths, setExtractOldValueForEditor, setPropertyValues, setPropertyValues, setPropertyValues, setPropertyValues`

    - ### Methods inherited from class org.springframework.beans.TypeConverterSupport

      `convertIfNecessary, convertIfNecessary, convertIfNecessary, convertIfNecessary`

    - ### Methods inherited from class org.springframework.beans.PropertyEditorRegistrySupport

      `copyCustomEditorsTo, copyDefaultEditorsTo, findCustomEditor, getConversionService, getDefaultEditor, guessPropertyTypeFromEditors, hasCustomEditorForElement, overrideDefaultEditor, registerCustomEditor, registerCustomEditor, registerDefaultEditors, setConversionService, useConfigValueEditors`

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

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

    - ### Methods inherited from interface org.springframework.beans.ConfigurablePropertyAccessor

      `getConversionService, setConversionService`

    - ### Methods inherited from interface org.springframework.beans.PropertyEditorRegistry

      `findCustomEditor, registerCustomEditor, registerCustomEditor`

    - ### Methods inherited from interface org.springframework.beans.TypeConverter

      `convertIfNecessary, convertIfNecessary, convertIfNecessary, convertIfNecessary`

- - ### Constructor Detail

    - #### AbstractNestablePropertyAccessor

          protected AbstractNestablePropertyAccessor()

      Create a new empty accessor. Wrapped instance needs to be set afterwards. Registers default editors.
      See Also:
        `setWrappedInstance(java.lang.Object)`

    - #### AbstractNestablePropertyAccessor

          protected AbstractNestablePropertyAccessor(boolean registerDefaultEditors)

      Create a new empty accessor. Wrapped instance needs to be set afterwards.
      Parameters:
        `registerDefaultEditors` - whether to register default editors (can be suppressed if the accessor won't need any type conversion)
      See Also:
        `setWrappedInstance(java.lang.Object)`

    - #### AbstractNestablePropertyAccessor

          protected AbstractNestablePropertyAccessor(Object object)

      Create a new accessor for the given object.
      Parameters:
        `object` - the object wrapped by this accessor

    - #### AbstractNestablePropertyAccessor

          protected AbstractNestablePropertyAccessor(Class<?> clazz)

      Create a new accessor, wrapping a new instance of the specified class.
      Parameters:
        `clazz` - class to instantiate and wrap

    - #### AbstractNestablePropertyAccessor

          protected AbstractNestablePropertyAccessor(Object object,
                                                     String nestedPath,
                                                     Object rootObject)

      Create a new accessor for the given object, registering a nested path that the object is in.
      Parameters:
        `object` - the object wrapped by this accessor
        `nestedPath` - the nested path of the object
        `rootObject` - the root object at the top of the path

    - #### AbstractNestablePropertyAccessor

          protected AbstractNestablePropertyAccessor(Object object,
                                                     String nestedPath,
                                                     AbstractNestablePropertyAccessor parent)

      Create a new accessor for the given object, registering a nested path that the object is in.
      Parameters:
        `object` - the object wrapped by this accessor
        `nestedPath` - the nested path of the object
        `parent` - the containing accessor (must not be `null`)

  - ### Method Detail

    - #### setAutoGrowCollectionLimit

          public void setAutoGrowCollectionLimit(int autoGrowCollectionLimit)

      Specify a limit for array and collection auto-growing.

      Default is unlimited on a plain accessor.

    - #### getAutoGrowCollectionLimit

          public int getAutoGrowCollectionLimit()

      Return the limit for array and collection auto-growing.

    - #### setWrappedInstance

          public void setWrappedInstance(Object object)

      Switch the target object, replacing the cached introspection results only if the class of the new object is different to that of the replaced object.
      Parameters:
        `object` - the new target object

    - #### setWrappedInstance

          public void setWrappedInstance(Object object,
                                         @Nullable
                                         String nestedPath,
                                         @Nullable
                                         Object rootObject)

      Switch the target object, replacing the cached introspection results only if the class of the new object is different to that of the replaced object.
      Parameters:
        `object` - the new target object
        `nestedPath` - the nested path of the object
        `rootObject` - the root object at the top of the path

    - #### getWrappedInstance

          public final Object getWrappedInstance()

    - #### getWrappedClass

          public final Class<?> getWrappedClass()

    - #### getNestedPath

          public final String getNestedPath()

      Return the nested path of the object wrapped by this accessor.

    - #### getRootInstance

          public final Object getRootInstance()

      Return the root object at the top of the path of this accessor.
      See Also:
        `getNestedPath()`

    - #### getRootClass

          public final Class<?> getRootClass()

      Return the class of the root object at the top of the path of this accessor.
      See Also:
        `getNestedPath()`

    - #### setPropertyValue

          public void setPropertyValue(String propertyName,
                                       @Nullable
                                       Object value)
                                throws BeansException

      Description copied from class: `AbstractPropertyAccessor`
      Actually set a property value.
      Specified by:
        `setPropertyValue` in interface `PropertyAccessor`
      Specified by:
        `setPropertyValue` in class `AbstractPropertyAccessor`
      Parameters:
        `propertyName` - name of the property to set value of
        `value` - the new value
      Throws:
        `InvalidPropertyException` - if there is no such property or if the property isn't writable
        `PropertyAccessException` - if the property was valid but the accessor method failed or a type mismatch occurred
        `BeansException`

    - #### setPropertyValue

          public void setPropertyValue(PropertyValue pv)
                                throws BeansException

      Description copied from interface: `PropertyAccessor`
      Set the specified value as current property value.
      Specified by:
        `setPropertyValue` in interface `PropertyAccessor`
      Overrides:
        `setPropertyValue` in class `AbstractPropertyAccessor`
      Parameters:
        `pv` - an object containing the new property value
      Throws:
        `InvalidPropertyException` - if there is no such property or if the property isn't writable
        `PropertyAccessException` - if the property was valid but the accessor method failed or a type mismatch occurred
        `BeansException`

    - #### setPropertyValue

          protected void setPropertyValue(AbstractNestablePropertyAccessor.PropertyTokenHolder tokens,
                                          PropertyValue pv)
                                   throws BeansException

      Throws:
        `BeansException`

    - #### getPropertyType

          @Nullable
          public Class<?> getPropertyType(String propertyName)
                                             throws BeansException

      Description copied from class: `PropertyEditorRegistrySupport`
      Determine the property type for the given property path.

      Called by `PropertyEditorRegistrySupport.findCustomEditor(java.lang.Class<?>, java.lang.String)` if no required type has been specified, to be able to find a type-specific editor even if just given a property path.

      The default implementation always returns `null`. BeanWrapperImpl overrides this with the standard `getPropertyType` method as defined by the BeanWrapper interface.

      Specified by:
        `getPropertyType` in interface `PropertyAccessor`
      Overrides:
        `getPropertyType` in class `AbstractPropertyAccessor`
      Parameters:
        `propertyName` - the property path to determine the type for
      Returns:
        the type of the property, or `null` if not determinable
      Throws:
        `PropertyAccessException` - if the property was valid but the accessor method failed
        `BeansException`
      See Also:
        `PropertyAccessor.getPropertyType(String)`

    - #### getPropertyTypeDescriptor

          @Nullable
          public TypeDescriptor getPropertyTypeDescriptor(String propertyName)
                                                             throws BeansException

      Description copied from interface: `PropertyAccessor`
      Return a type descriptor for the specified property: preferably from the read method, falling back to the write method.
      Parameters:
        `propertyName` - the property to check (may be a nested path and/or an indexed/mapped property)
      Returns:
        the property type for the particular property, or `null` if not determinable
      Throws:
        `PropertyAccessException` - if the property was valid but the accessor method failed
        `BeansException`

    - #### isReadableProperty

          public boolean isReadableProperty(String propertyName)

      Description copied from interface: `PropertyAccessor`
      Determine whether the specified property is readable.

      Returns `false` if the property doesn't exist.

      Parameters:
        `propertyName` - the property to check (may be a nested path and/or an indexed/mapped property)
      Returns:
        whether the property is readable

    - #### isWritableProperty

          public boolean isWritableProperty(String propertyName)

      Description copied from interface: `PropertyAccessor`
      Determine whether the specified property is writable.

      Returns `false` if the property doesn't exist.

      Parameters:
        `propertyName` - the property to check (may be a nested path and/or an indexed/mapped property)
      Returns:
        whether the property is writable

    - #### convertForProperty

          @Nullable
          protected Object convertForProperty(String propertyName,
                                                        @Nullable
                                                        Object oldValue,
                                                        @Nullable
                                                        Object newValue,
                                                        TypeDescriptor td)
                                                 throws TypeMismatchException

      Throws:
        `TypeMismatchException`

    - #### getPropertyValue

          @Nullable
          public Object getPropertyValue(String propertyName)
                                            throws BeansException

      Description copied from class: `AbstractPropertyAccessor`
      Actually get the value of a property.
      Specified by:
        `getPropertyValue` in interface `PropertyAccessor`
      Specified by:
        `getPropertyValue` in class `AbstractPropertyAccessor`
      Parameters:
        `propertyName` - name of the property to get the value of
      Returns:
        the value of the property
      Throws:
        `InvalidPropertyException` - if there is no such property or if the property isn't readable
        `PropertyAccessException` - if the property was valid but the accessor method failed
        `BeansException`

    - #### getPropertyValue

          @Nullable
          protected Object getPropertyValue(AbstractNestablePropertyAccessor.PropertyTokenHolder tokens)
                                               throws BeansException

      Throws:
        `BeansException`

    - #### getPropertyHandler

          @Nullable
          protected AbstractNestablePropertyAccessor.PropertyHandler getPropertyHandler(String propertyName)
                                                                                           throws BeansException

      Return the `AbstractNestablePropertyAccessor.PropertyHandler` for the specified `propertyName`, navigating if necessary. Return `null` if not found rather than throwing an exception.
      Parameters:
        `propertyName` - the property to obtain the descriptor for
      Returns:
        the property descriptor for the specified property, or `null` if not found
      Throws:
        `BeansException` - in case of introspection failure

    - #### getLocalPropertyHandler

          @Nullable
          protected abstract AbstractNestablePropertyAccessor.PropertyHandler getLocalPropertyHandler(String propertyName)

      Return a `AbstractNestablePropertyAccessor.PropertyHandler` for the specified local `propertyName`. Only used to reach a property available in the current context.
      Parameters:
        `propertyName` - the name of a local property
      Returns:
        the handler for that property, or `null` if it has not been found

    - #### newNestedPropertyAccessor

          protected abstract AbstractNestablePropertyAccessor newNestedPropertyAccessor(Object object,
                                                                                        String nestedPath)

      Create a new nested property accessor instance. Can be overridden in subclasses to create a PropertyAccessor subclass.
      Parameters:
        `object` - the object wrapped by this PropertyAccessor
        `nestedPath` - the nested path of the object
      Returns:
        the nested PropertyAccessor instance

    - #### createNotWritablePropertyException

          protected abstract NotWritablePropertyException createNotWritablePropertyException(String propertyName)

      Create a `NotWritablePropertyException` for the specified property.

    - #### getFinalPath

          protected String getFinalPath(AbstractNestablePropertyAccessor pa,
                                        String nestedPath)

      Get the last component of the path. Also works if not nested.
      Parameters:
        `pa` - property accessor to work on
        `nestedPath` - property path we know is nested
      Returns:
        last component of the path (the property on the target bean)

    - #### getPropertyAccessorForPropertyPath

          protected AbstractNestablePropertyAccessor getPropertyAccessorForPropertyPath(String propertyPath)

      Recursively navigate to return a property accessor for the nested property path.
      Parameters:
        `propertyPath` - property path, which may be nested
      Returns:
        a property accessor for the target bean

    - #### toString

          public String toString()

      Overrides:
        `toString` in class `Object`