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