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