001package org.apache.commons.beanutils2;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.util.Map;
023
024/**
025 * Provides access to properties and methods of a bean.
026 *
027 * @param <B> the type of the bean this BeanAcessor is associated with.
028 */
029public interface BeanAccessor<B>
030{
031
032    // get
033
034    /**
035     * Gets the value of the property with name {@code propertyName} from the bean wrapped by this BeanAccessor. The
036     * value will be wrapped in a {@code BeanAccessor} to enable fluent calls.
037     *
038     * @param propertyName the name of the property to get the value from. Must not be {@code null}!
039     * @return a {@code BeanAccessor} wrapping the properties value.
040     */
041    BeanAccessor<?> get( String propertyName );
042
043    /**
044     * Selects the indexed property with name {@code propertyName} from the bean wrapped by this {@code BeanAccessor}. A
045     * {@link IndexedPropertyGetterAccessor} will be returned for specifying the index to return the value of.
046     *
047     * @param propertyName the name of the indexed property to select. Must not be {@code null}!
048     * @return a {@link IndexedPropertyGetterAccessor} for specifying the index to return the value of.
049     */
050    IndexedPropertyGetterAccessor<?> getIndexed( String propertyName );
051
052    /**
053     * Selects the mapped property with name {@code propertyName} from the bean wrapped by this {@code BeanAccessor}. A
054     * {@link MappedPropertyGetterAccessor} will be returned for specifying the key to return the value of.
055     *
056     * @param propertyName the name of the mapped property to select. Must not be {@code null}!
057     * @return a {@link MappedPropertyGetterAccessor} for specifying the key to return the value of.
058     */
059    MappedPropertyGetterAccessor getMapped( String propertyName );
060
061    /**
062     * Gets the bean wrapped by this {@code BeanAccessor}.
063     *
064     * @return the bean.
065     */
066    B get();
067
068    /**
069     * Tries to cast the bean wrapped by this {@code BeanAccessor} an returns the result.
070     *
071     * @param <V> the type to cast the wrapped bean to.
072     * @return the wrapped bean, casted to type {@code V}.
073     */
074    <V> V cast();
075
076    // set
077
078    /**
079     * Selects the property with name {@code propertyName} for setting a new value. A {@link BeanPropertySetter} will be
080     * returned for specifying the new value.
081     *
082     * @param propertyName the name of the property to select for setting a new value. Must not be {@code null}.
083     * @return a {@link BeanPropertySetter} for setting a new value.
084     */
085    BeanPropertySetter<B> set( String propertyName );
086
087    /**
088     * Selects the indexed property with name {@code propertyName} for setting a new value. A
089     * {@link IndexedPropertySetterAccessor} will be returned for specifying the index to set a new value to.
090     *
091     * @param propertyName the name of the indexed property to select for setting a new value. Must not be {@code null}.
092     * @return a {@link IndexedPropertySetterAccessor} for setting a new value.
093     */
094    IndexedPropertySetterAccessor<B> setIndexed( String propertyName );
095
096    /**
097     * Selects the mapped property with name {@code propertyName} for setting a new value. A
098     * {@link MappedPropertySetterAccessor} will be returned for specifying the key to set a new value to.
099     *
100     * @param propertyName the name of the mapped property to select for setting a new value. Must not be {@code null}.
101     * @return a {@link MappedPropertySetterAccessor} for setting a new value.
102     */
103    MappedPropertySetterAccessor<B> setMapped( String propertyName );
104
105    // clone
106
107    /**
108     * Clones a bean based on the available property getters and setters, even if the bean class itself does not
109     * implement Cloneable.
110     * <p>
111     * <strong>Note:</strong> this method creates a <strong>shallow</strong> clone. In other words, any objects referred
112     * to by the bean are shared with the clone rather than being cloned in turn.
113     *
114     * @return the cloned bean
115     */
116    B cloneBean();
117
118    /**
119     * Copies property values from the bean wrapped by this {@code BeanAccessor} to {@code target} for all cases where
120     * the property names are the same. For each property, a conversion is attempted as necessary.
121     * <p>
122     * <strong>Note</strong> that this method is intended to perform a "shallow copy" of the properties and so complex
123     * properties (for example, nested ones) will not be copied.
124     * <p>
125     * <strong>TODO</strong> should we implement something like the following?
126     * <p>
127     * If you know that no type conversions are required, the <code>copyProperties()</code> method in
128     * {@link PropertyUtils} will execute faster than this method.
129     * <p>
130     * <strong>FIXME</strong> - Indexed and mapped properties that do not have getter and setter methods for the
131     * underlying array or Map are not copied by this method.
132     *
133     * @param <T> the type of the bean to copy properties to.
134     * @param target the target to copy properties to from the wrapped bean
135     */
136    <T extends B> void copyPropertiesTo( T target );
137
138    // description
139
140    /**
141     * Return the entire set of properties for which the specified bean provides a read method. This map contains the
142     * property names as keys and the property values as values, for all properties the bean provides a read method for
143     * (i.e. where the getReadMethod() returns non-null).
144     * <p>
145     * This map can be fed back to a call to <code>BeanAccessor.populate()</code> to reconstitute the same set of
146     * properties, modulo differences for read-only and write-only properties, but only if there are no indexed
147     * properties.
148     * <p>
149     * <strong>Warning:</strong> if any of the bean property implementations contain (directly or indirectly) a call to
150     * this method then a stack overflow may result. For example: <code><pre>
151     * class MyBean
152     * {
153     *    public Map&lt;String, Object&gt; getParameterMap()
154     *    {
155     *         on( this ).describe;
156     *    }
157     * }
158     * </pre></code> will result in an infinite regression when <code>getParametersMap</code> is called. It is
159     * recommended that such methods are given alternative names (for example, <code>parametersMap</code>).
160     *
161     * @return Map that contains the property names as keys and property values as values.
162     */
163    Map<String, Object> describe();
164
165    /**
166     * Populate {@code properties} to the bean wrapped by this {@code BeanAccessor}. The map of properties passed to
167     * this method has to specify names of properties to set and corresponding values as key-value-pairs.
168     *
169     * @param properties Map keyed by property name, with the corresponding value to be set.
170     *            Must not be {@code null}.
171     */
172    void populate( Map<String, Object> properties );
173
174    // methods invocation
175
176    /**
177     * Invokes the method with name {@code methodName}. An {@link ArgumentsAccessor} will be returned to specify the
178     * parameters for the method invocation.
179     *
180     * @param methodName the name of the method to invoke. Must not be {@code null}!
181     * @return an {@link ArgumentsAccessor} to specify arguments for the method invocation.
182     */
183    ArgumentsAccessor invoke( String methodName );
184
185    /**
186     * Invokes the method with name {@code methodName} and the exact arguments. An {@link ArgumentsAccessor} will be
187     * returned to specify the parameters for the method invocation.
188     *
189     * @param methodName the name of the method to invoke. Must not be {@code null}!
190     * @return a {@link ArgumentsAccessor} to specify any arguments
191     */
192    ArgumentsAccessor invokeExact( String methodName );
193
194}