001/*
002 * Copyright 2002-2017 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.beans;
018
019import java.util.Map;
020
021import org.springframework.core.convert.TypeDescriptor;
022
023/**
024 * Common interface for classes that can access named properties
025 * (such as bean properties of an object or fields in an object)
026 * Serves as base interface for {@link BeanWrapper}.
027 *
028 * @author Juergen Hoeller
029 * @since 1.1
030 * @see BeanWrapper
031 * @see PropertyAccessorFactory#forBeanPropertyAccess
032 * @see PropertyAccessorFactory#forDirectFieldAccess
033 */
034public interface PropertyAccessor {
035
036        /**
037         * Path separator for nested properties.
038         * Follows normal Java conventions: getFoo().getBar() would be "foo.bar".
039         */
040        String NESTED_PROPERTY_SEPARATOR = ".";
041        char NESTED_PROPERTY_SEPARATOR_CHAR = '.';
042
043        /**
044         * Marker that indicates the start of a property key for an
045         * indexed or mapped property like "person.addresses[0]".
046         */
047        String PROPERTY_KEY_PREFIX = "[";
048        char PROPERTY_KEY_PREFIX_CHAR = '[';
049
050        /**
051         * Marker that indicates the end of a property key for an
052         * indexed or mapped property like "person.addresses[0]".
053         */
054        String PROPERTY_KEY_SUFFIX = "]";
055        char PROPERTY_KEY_SUFFIX_CHAR = ']';
056
057
058        /**
059         * Determine whether the specified property is readable.
060         * <p>Returns {@code false} if the property doesn't exist.
061         * @param propertyName the property to check
062         * (may be a nested path and/or an indexed/mapped property)
063         * @return whether the property is readable
064         */
065        boolean isReadableProperty(String propertyName);
066
067        /**
068         * Determine whether the specified property is writable.
069         * <p>Returns {@code false} if the property doesn't exist.
070         * @param propertyName the property to check
071         * (may be a nested path and/or an indexed/mapped property)
072         * @return whether the property is writable
073         */
074        boolean isWritableProperty(String propertyName);
075
076        /**
077         * Determine the property type for the specified property,
078         * either checking the property descriptor or checking the value
079         * in case of an indexed or mapped element.
080         * @param propertyName the property to check
081         * (may be a nested path and/or an indexed/mapped property)
082         * @return the property type for the particular property,
083         * or {@code null} if not determinable
084         * @throws PropertyAccessException if the property was valid but the
085         * accessor method failed
086         */
087        Class<?> getPropertyType(String propertyName) throws BeansException;
088
089        /**
090         * Return a type descriptor for the specified property:
091         * preferably from the read method, falling back to the write method.
092         * @param propertyName the property to check
093         * (may be a nested path and/or an indexed/mapped property)
094         * @return the property type for the particular property,
095         * or {@code null} if not determinable
096         * @throws PropertyAccessException if the property was valid but the
097         * accessor method failed
098         */
099        TypeDescriptor getPropertyTypeDescriptor(String propertyName) throws BeansException;
100
101        /**
102         * Get the current value of the specified property.
103         * @param propertyName the name of the property to get the value of
104         * (may be a nested path and/or an indexed/mapped property)
105         * @return the value of the property
106         * @throws InvalidPropertyException if there is no such property or
107         * if the property isn't readable
108         * @throws PropertyAccessException if the property was valid but the
109         * accessor method failed
110         */
111        Object getPropertyValue(String propertyName) throws BeansException;
112
113        /**
114         * Set the specified value as current property value.
115         * @param propertyName the name of the property to set the value of
116         * (may be a nested path and/or an indexed/mapped property)
117         * @param value the new value
118         * @throws InvalidPropertyException if there is no such property or
119         * if the property isn't writable
120         * @throws PropertyAccessException if the property was valid but the
121         * accessor method failed or a type mismatch occurred
122         */
123        void setPropertyValue(String propertyName, Object value) throws BeansException;
124
125        /**
126         * Set the specified value as current property value.
127         * @param pv an object containing the new property value
128         * @throws InvalidPropertyException if there is no such property or
129         * if the property isn't writable
130         * @throws PropertyAccessException if the property was valid but the
131         * accessor method failed or a type mismatch occurred
132         */
133        void setPropertyValue(PropertyValue pv) throws BeansException;
134
135        /**
136         * Perform a batch update from a Map.
137         * <p>Bulk updates from PropertyValues are more powerful: This method is
138         * provided for convenience. Behavior will be identical to that of
139         * the {@link #setPropertyValues(PropertyValues)} method.
140         * @param map Map to take properties from. Contains property value objects,
141         * keyed by property name
142         * @throws InvalidPropertyException if there is no such property or
143         * if the property isn't writable
144         * @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
145         * occurred for specific properties during the batch update. This exception bundles
146         * all individual PropertyAccessExceptions. All other properties will have been
147         * successfully updated.
148         */
149        void setPropertyValues(Map<?, ?> map) throws BeansException;
150
151        /**
152         * The preferred way to perform a batch update.
153         * <p>Note that performing a batch update differs from performing a single update,
154         * in that an implementation of this class will continue to update properties
155         * if a <b>recoverable</b> error (such as a type mismatch, but <b>not</b> an
156         * invalid field name or the like) is encountered, throwing a
157         * {@link PropertyBatchUpdateException} containing all the individual errors.
158         * This exception can be examined later to see all binding errors.
159         * Properties that were successfully updated remain changed.
160         * <p>Does not allow unknown fields or invalid fields.
161         * @param pvs PropertyValues to set on the target object
162         * @throws InvalidPropertyException if there is no such property or
163         * if the property isn't writable
164         * @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
165         * occurred for specific properties during the batch update. This exception bundles
166         * all individual PropertyAccessExceptions. All other properties will have been
167         * successfully updated.
168         * @see #setPropertyValues(PropertyValues, boolean, boolean)
169         */
170        void setPropertyValues(PropertyValues pvs) throws BeansException;
171
172        /**
173         * Perform a batch update with more control over behavior.
174         * <p>Note that performing a batch update differs from performing a single update,
175         * in that an implementation of this class will continue to update properties
176         * if a <b>recoverable</b> error (such as a type mismatch, but <b>not</b> an
177         * invalid field name or the like) is encountered, throwing a
178         * {@link PropertyBatchUpdateException} containing all the individual errors.
179         * This exception can be examined later to see all binding errors.
180         * Properties that were successfully updated remain changed.
181         * @param pvs PropertyValues to set on the target object
182         * @param ignoreUnknown should we ignore unknown properties (not found in the bean)
183         * @throws InvalidPropertyException if there is no such property or
184         * if the property isn't writable
185         * @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
186         * occurred for specific properties during the batch update. This exception bundles
187         * all individual PropertyAccessExceptions. All other properties will have been
188         * successfully updated.
189         * @see #setPropertyValues(PropertyValues, boolean, boolean)
190         */
191        void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown)
192                        throws BeansException;
193
194        /**
195         * Perform a batch update with full control over behavior.
196         * <p>Note that performing a batch update differs from performing a single update,
197         * in that an implementation of this class will continue to update properties
198         * if a <b>recoverable</b> error (such as a type mismatch, but <b>not</b> an
199         * invalid field name or the like) is encountered, throwing a
200         * {@link PropertyBatchUpdateException} containing all the individual errors.
201         * This exception can be examined later to see all binding errors.
202         * Properties that were successfully updated remain changed.
203         * @param pvs PropertyValues to set on the target object
204         * @param ignoreUnknown should we ignore unknown properties (not found in the bean)
205         * @param ignoreInvalid should we ignore invalid properties (found but not accessible)
206         * @throws InvalidPropertyException if there is no such property or
207         * if the property isn't writable
208         * @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions
209         * occurred for specific properties during the batch update. This exception bundles
210         * all individual PropertyAccessExceptions. All other properties will have been
211         * successfully updated.
212         */
213        void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
214                        throws BeansException;
215
216}