    001// Licensed under the Apache License, Version 2.0 (the "License");
    002// you may not use this file except in compliance with the License.
    003// You may obtain a copy of the License at
    004//
    005//     http://www.apache.org/licenses/LICENSE-2.0
    006//
    007// Unless required by applicable law or agreed to in writing, software
    008// distributed under the License is distributed on an "AS IS" BASIS,
    009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    010// See the License for the specific language governing permissions and
    011// limitations under the License.
    012
    013package org.apache.tapestry5.beanmodel;
    014
    015import java.util.List;
    016
    017import org.apache.tapestry5.beaneditor.DataType;
    018import org.apache.tapestry5.beaneditor.RelativePosition;
    019
    020/**
    021 * Provides the information necessary to build a user interface to view, create or edit an instance of a particular
    022 * type.
    023 *
    024 * BeanModels are not thread-safe, they are also not serializable.
    025 *
    026 * Here, and in {@link org.apache.tapestry5.beanmodel.PropertyModel}, the term "propertyName" is used for simplicitly.
    027 * However, a full {@linkplain org.apache.tapestry5.beanmodel.services.PropertyConduitSource#create(Class, String) property
    028 * expression} may be utilized when {@linkplain #add(String) adding new properties to an existing BeanModel}.
    029 *
    030 * @see org.apache.tapestry5.beanmodel.services.BeanModelSource
    031 */
    032public interface BeanModel<T>
    033{
    034    /**
    035     * Returns the type of bean for which this model was initially created.
    036     */
    037    Class<T> getBeanType();
    038
    039
    040    /**
    041     * Creates a new bean instance.  This is based on {@link org.apache.tapestry5.commons.ObjectLocator#autobuild(Class)},
    042     * so a public constructor will be used, and dependencies injected.
    043     *
    044     * @return new instance of the bean
    045     */
    046    T newInstance();
    047
    048    /**
    049     * Returns a list of the editable properties of the bean, in <em>presentation</em> order.
    050     */
    051    List<String> getPropertyNames();
    052
    053    /**
    054     * Returns the named model.
    055     *
    056     * @param propertyName name of property to retrieve model for (case is ignored)
    057     * @return the model for the property
    058     * @throws RuntimeException if the bean editor model does not have a property model for the provided name
    059     */
    060    PropertyModel get(String propertyName);
    061
    062    /**
    063     * Returns the identified model.  Property ids are a stripped version of the property name. Case is ignored.
    064     *
    065     * @param propertyId matched caselessly against {@link org.apache.tapestry5.beanmodel.PropertyModel#getId()}
    066     * @throws RuntimeException if the bean editor model does not have a property model with the indicated id
    067     */
    068    PropertyModel getById(String propertyId);
    069
    070    /**
    071     * Adds a new property to the model, returning its mutable model for further refinement. The property is added to
    072     * the <em>end</em> of the list of properties. The property must be real (but may have been excluded if there was no
    073     * {@linkplain org.apache.tapestry5.beaneditor.DataType datatype} associated with the property). To add a synthetic
    074     * property, use {@link #add(String, org.apache.tapestry5.beanmodel.PropertyConduit)}
    075     *
    076     * @param propertyName name of property to add
    077     * @return the new property model (for further configuration)
    078     * @throws RuntimeException if the property already exists
    079     */
    080    PropertyModel add(String propertyName);
    081
    082
    083    /**
    084     * Adds a new synthetic property to the model, returning its mutable model for further refinement. The property is added to
    085     * the <em>end</em> of the list of properties.
    086     *
    087     * @param propertyName name of property to add
    088     * @param expression   expression for the property
    089     * @return the new property model (for further configuration)
    090     * @throws RuntimeException if the property already exists
    091     * @since 5.3
    092     */
    093    PropertyModel addExpression(String propertyName, String expression);
    094
    095    /**
    096     * Adds an empty property (one with no property conduit).
    097     *
    098     * @param propertyName name of property to add
    099     * @return the new property model (for further configuration)
    100     * @throws RuntimeException if the property already exists
    101     * @since 5.3
    102     */
    103    PropertyModel addEmpty(String propertyName);
    104
    105    /**
    106     * Adds a new property to the model (as with {@link #add(String)}), ordered before or after an existing property.
    107     *
    108     * @param position             controls whether the new property is ordered before or after the existing property
    109     * @param existingPropertyName the name of an existing property (this must exist)
    110     * @param propertyName         the new property to add
    111     * @return the new property model (for further configuration)
    112     * @throws RuntimeException if the existing property does not exist, or if the new property already does exist
    113     */
    114    PropertyModel add(RelativePosition position, String existingPropertyName, String propertyName);
    115
    116    /**
    117     * Adds a new property to the model, ordered before or after an existing property.
    118     *
    119     * @param position             controls whether the new property is ordered before or after the existing property
    120     * @param existingPropertyName the name of an existing property (this must exist)
    121     * @param propertyName         the new property to add
    122     * @param conduit              conduit used to read or update the property; this may be null for a synthetic or
    123     *                             placeholder property
    124     * @return the new property model (for further configuration)
    125     * @throws RuntimeException if the existing property does not exist, or if the new property already does exist
    126     */
    127    PropertyModel add(RelativePosition position, String existingPropertyName, String propertyName,
    128                      PropertyConduit conduit);
    129
    130    /**
    131     * Adds a new, synthetic property to the model, returning its mutable model for further refinement.
    132     *
    133     * @param propertyName name of property to add
    134     * @param conduit      the conduit used to read or update the property; this may be null for a synthetic or
    135     *                     placeholder property.  Instead of passing null, please invoke {@link #addEmpty(String)}.
    136     * @return the model for the property
    137     * @throws RuntimeException if the property already exists
    138     * @see #addExpression(String, String)
    139     */
    140    PropertyModel add(String propertyName, PropertyConduit conduit);
    141
    142    /**
    143     * Removes the named properties from the model, if present. It is not considered an error to remove a property that
    144     * does not exist.
    145     *
    146     * @param propertyNames the names of properties to be removed (case insensitive)
    147     * @return the model for further modifications
    148     */
    149    BeanModel<T> exclude(String... propertyNames);
    150
    151    /**
    152     * Re-orders the properties of the model into the specified order. Existing properties that are not indicated are
    153     * retained, but ordered to the end of the list.
    154     *
    155     * @param propertyNames property names in order they should be displayed (case insensitive)
    156     * @return the model for further modifications
    157     */
    158    BeanModel<T> reorder(String... propertyNames);
    159
    160    /**
    161     * Re-orders the properties of the model into the specified order. Existing properties that are not indicated are
    162     * removed.
    163     *
    164     * @param propertyNames the names of properties to be retained
    165     * @return the model for further modifications
    166     */
    167    BeanModel<T> include(String... propertyNames);
    168}