001: /*
002: * $Id: PropertyModel.java 460374 2006-04-24 15:29:16Z gwynevans $
003: * $Revision: 460374 $ $Date: 2006-04-24 17:29:16 +0200 (Mon, 24 Apr 2006) $
004: *
005: * ==============================================================================
006: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
007: * use this file except in compliance with the License. You may obtain a copy of
008: * the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015: * License for the specific language governing permissions and limitations under
016: * the License.
017: */
018: package wicket.model;
019:
020: import wicket.Component;
021: import wicket.util.lang.PropertyResolver;
022:
023: /**
024: * A PropertyModel is used to dynamically access a model using a "property
025: * expression". See {@link PropertyResolver} javadoc for allowed property
026: * expressions.
027: * <p>
028: * For example, take the following bean:
029: *
030: * <pre>
031: * public class Person
032: * {
033: * private String name;
034: *
035: * public String getName()
036: * {
037: * return name;
038: * }
039: *
040: * public void setName(String name)
041: * {
042: * this.name = name;
043: * }
044: * }
045: * </pre>
046: *
047: * We could construct a label that dynamically fetches the name property of the
048: * given person object like this:
049: *
050: * <pre>
051: * Person person = getSomePerson();
052: * ...
053: * add(new Label("myLabel", new PopertyModel(person, "name"));
054: * </pre>
055: *
056: * Where 'myLabel' is the name of the component, and 'name' is the property
057: * expression to get the name property.
058: * </p>
059: * <p>
060: * In the same fashion, we can create form components that work dynamically on
061: * the given model object. For instance, we could create a text field that
062: * updates the name property of a person like this:
063: *
064: * <pre>
065: * add(new TextField("myTextField", new PropertyModel(person, "name"));
066: * </pre>
067: *
068: * </p>
069: * <p>
070: * To force conversion of property value to a specific type, you can provide
071: * constructor argument 'propertyType'. if that is set, that type is used for
072: * conversion instead of the type that is figured out by
073: * {@link PropertyResolver}. This can be especially useful for when you have a
074: * generic property (like Serializable myProp) that you want to be converted to
075: * a narrower type (e.g. an Integer). {@link PropertyResolver} sees an incomming
076: * string being compatible with the target property, and will then bypass the
077: * converter. Hence, to force myProp being converted to and from an integer,
078: * propertyType should be set to Integer.
079: * </p>
080: *
081: * @see wicket.model.IModel
082: * @see wicket.model.Model
083: * @see wicket.model.AbstractDetachableModel
084: *
085: * @author Chris Turner
086: * @author Eelco Hillenius
087: * @author Jonathan Locke
088: */
089: public class PropertyModel extends AbstractPropertyModel {
090: private static final long serialVersionUID = 1L;
091:
092: /** Property expression for property access. */
093: private final String expression;
094:
095: /**
096: * If this is set, this type is used for conversion instead of the type that
097: * is figured out by the property expression code. This can be especially
098: * useful for when you have a generic property (like Serializable myProp)
099: * that you want to be converted to a narrower type (e.g. an Integer). The
100: * property expression code sees an incoming string being compatible with
101: * the target property, and will then bypass the converter. Hence, to force
102: * myProp being converted to and from an integer, propertyType should be set
103: * to Integer.
104: */
105: private final Class propertyType;
106:
107: /**
108: * Construct with a wrapped (IModel) or unwrapped (non-IModel) object and a
109: * property expression that works on the given model. Additional formatting
110: * will be used depending on the configuration setting.
111: *
112: * @param modelObject
113: * The model object, which may or may not implement IModel
114: * @param expression
115: * Property expression for property access
116: */
117: public PropertyModel(final Object modelObject,
118: final String expression) {
119: this (modelObject, expression, null);
120: }
121:
122: /**
123: * Construct with a wrapped (IModel) or unwrapped (non-IModel) object and a
124: * property expression that works on the given model. Additional formatting
125: * will be used depending on the configuration setting.
126: *
127: * @param modelObject
128: * The model object, which may or may not implement IModel
129: * @param expression
130: * Property expression for property access
131: * @param propertyType
132: * The type to be used for conversion instead of the type that is
133: * figured out by the property expression code. This can be
134: * especially useful for when you have a generic property (like
135: * Serializable myProp) that you want to be converted to a
136: * narrower type (e.g. an Integer). The property expression code
137: * sees an incoming string being compatible with the target
138: * property, and will then bypass the converter. Hence, to force
139: * myProp being converted to and from an integer, propertyType
140: * should be set to Integer.
141: */
142: public PropertyModel(final Object modelObject,
143: final String expression, Class propertyType) {
144: super (modelObject);
145: this .expression = expression;
146: this .propertyType = propertyType;
147: }
148:
149: /**
150: * @see java.lang.Object#toString()
151: */
152: public String toString() {
153: StringBuffer sb = new StringBuffer(super .toString());
154: sb.append(":expression=[").append(expression).append("]");
155: sb.append(":propertyType=[").append(propertyType).append("]");
156: return sb.toString();
157: }
158:
159: /**
160: * @see wicket.model.AbstractPropertyModel#propertyExpression(wicket.Component)
161: */
162: protected String propertyExpression(Component component) {
163: return expression;
164: }
165:
166: /**
167: * @see wicket.model.AbstractPropertyModel#propertyType(wicket.Component)
168: */
169: protected Class propertyType(Component component) {
170: return propertyType;
171: }
172: }
|