KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > inversoft > beans > BeanProperty


1 /*
2  * Copyright (c) 2003, Inversoft
3  *
4  * This software is distribuable under the GNU Lesser General Public License.
5  * For more information visit gnu.org.
6  */

7 package com.inversoft.beans;
8
9
10 import java.lang.reflect.Method JavaDoc;
11 import java.util.HashMap JavaDoc;
12 import java.util.Map JavaDoc;
13
14 import com.inversoft.util.ObjectTools;
15 import com.inversoft.util.typeconverter.TypeConversionException;
16
17
18 /**
19  * This class is used to describe, and manipulate JavaBean
20  * properties. The properties that this class handles are
21  * normal properties and NOT nested properties (see {@link
22  * NestedBeanProperty NestedBeanProperty} for more
23  * information on nested bean properties).
24  *
25  * @author Brian Pontarelli
26  */

27 public class BeanProperty extends BaseBeanProperty {
28
29     /**
30      * Global switch for caching
31      */

32     static final boolean CACHING = true;
33
34     /**
35      * The cache Map for the BeanProperty objects (unsynchronized)
36      */

37     static Map JavaDoc cache = new HashMap JavaDoc();
38
39     protected Method JavaDoc read;
40     protected Method JavaDoc write;
41     protected boolean collection;
42
43
44     //--------------------------------------------------------------------------
45
// Cache Methods
46
//--------------------------------------------------------------------------
47

48     /**
49      * Returns an instance of the BeanProperty for the given propertyName and
50      * bean Class. This object might be cached, depending on the implementation
51      * of this method. Therefore, you must take into account a cached or non-
52      * cached object.
53      *
54      * @param propertyName The property name of the BeanProperty
55      * @param beanClass The bean Class
56      * @return The BeanProperty and never null
57      * @throws BeanException If the creation of the obejct fails
58      */

59     public static BeanProperty getInstance(String JavaDoc propertyName, Class JavaDoc beanClass)
60     throws BeanException {
61
62         if (propertyName == null || propertyName.indexOf(".") != -1) {
63             throw new BeanException("Invalid propertyName: " + propertyName);
64         }
65
66         // If not caching, just create the objects
67
if (!CACHING) {
68             return new BeanProperty(propertyName, beanClass);
69         }
70
71         synchronized (cache) {
72             // Otherwise look for the property Map or create and store
73
Map JavaDoc propMap = (Map JavaDoc) cache.get(beanClass);
74             if (propMap == null) {
75                 propMap = new HashMap JavaDoc();
76                 cache.put(beanClass, propMap);
77             }
78
79             // Look for the property itself, or create and store
80
BeanProperty bp = (BeanProperty) propMap.get(propertyName);
81             if (bp == null) {
82                 bp = new SynchronizedBeanProperty(propertyName, beanClass);
83                 propMap.put(propertyName, bp);
84             } else {
85                 if (bp.getClass() != SynchronizedBeanProperty.class) {
86                     throw new BeanException("Looking for non-indexed property " +
87                         "but cached version is indexed");
88                 }
89             }
90
91             return bp;
92         }
93     }
94
95
96
97     /**
98      * Default constructor that can be used by sub-classes that want to delay the
99      * initialization of the propertyName and beanClass or that do not use these
100      * members. This constructor also calls the default constructor from the
101      * BaseBeanProperty super-class. This means that using this constructor will
102      * not make a template method call to {@link #initialize() #initialize()}.
103      */

104     protected BeanProperty() {
105         super();
106     }
107
108     /**
109      * <p>
110      * Constructs a new bean property using the property name and the bean class
111      * given.
112      * </p>
113      *
114      * <p>
115      * If the bean class does not have a write method (set method) than the property
116      * is considered read-only. The bean class MUST have a read method (get method)
117      * or this method will throw and exception. This method calls the super-class
118      * constructor with the same signature.
119      * </p>
120      *
121      * @param propertyName The name of the JavaBean property
122      * @param beanClass The Class object used to find the read and write methods
123      * for the JavaBean property
124      * @throws BeanException If the property is invalid or does not exist in the
125      * bean class given
126      */

127     public BeanProperty(String JavaDoc propertyName, Class JavaDoc beanClass)
128     throws BeanException {
129         super(propertyName, beanClass); // Super constructor calls initialize
130
}
131
132     /**
133      * <p>
134      * Constructs a new bean property using the property name and the fully qualified
135      * name of the bean class given.
136      * </p>
137      *
138      * <p>
139      * If the bean class does not have a write method (set method) than the property
140      * is considered read-only. The bean class MUST have a read method (get method)
141      * or this method will throw and exception. This method calls the super-class
142      * constructor with the same signature.
143      * </p>
144      *
145      * @param propertyName The name of the JavaBean property
146      * @param beanClass The fuly qualified name of the bean class object used to find
147      * the read and write methods for the Java bean property
148      * @throws BeanException If the property is invalid or does not exist in the
149      * bean class given
150      */

151     public BeanProperty(String JavaDoc propertyName, String JavaDoc beanClass)
152     throws BeanException {
153         super(propertyName, beanClass); // Super constructor calls initialize
154
}
155
156     /**
157      * Initializes the bean property by finding the read and write methods and setting
158      * up the propertyType for this BeanProperty.
159      *
160      * @throws BeanException If the bean class does not contain the property
161      */

162     protected void initialize() throws BeanException {
163
164         read = JavaBeanTools.findReadMethod(propertyName, beanClass);
165         propertyType = read.getReturnType();
166         collection = ObjectTools.isCollection(propertyType);
167
168         try {
169             write = JavaBeanTools.findWriteMethod(propertyName, beanClass, propertyType);
170         } catch (BeanException be) {
171             // smother the exception so that this property is read only
172
}
173     }
174
175     /**
176      * Returns the bean class that the property is defined in
177      */

178     public Class JavaDoc getBeanClass() {
179         return beanClass;
180     }
181
182     /**
183      * Returns the read method of the bean property
184      */

185     public Method JavaDoc getReadMethod() {
186         return read;
187     }
188
189     /**
190      * Returns the write method name of the bean property
191      */

192     public Method JavaDoc getWriteMethod() {
193         return write;
194     }
195
196     /**
197      * Returns the value of the Java bean property for the given bean instance.
198      *
199      * @param bean The instance of the Java bean to retrieve the property from
200      * @return The value of the property retrieved by calling the read method of
201      * the property
202      * @throws BeanException If there was an error getting the Java bean property or
203      * the getter/is method threw a checked Exception
204      */

205     public Object JavaDoc getPropertyValue(final Object JavaDoc bean) throws BeanException {
206         Object JavaDoc value = JavaBeanTools.callGetter(this, bean);
207
208         if (hasPropertyListeners()) {
209             firePropertyEvent(GET, value, value, bean, null);
210         }
211
212         return value;
213     }
214
215     /**
216      * This operation is not supported except on IndexedBeanProperty. This is
217      * here for code ease in JavaBean and that is why it is package level.
218      * IndexedBeanProperty opens it to public.
219      *
220      * @throws BeanException Always
221      */

222     public Object JavaDoc getPropertyValue(final Object JavaDoc bean, final Object JavaDoc key)
223     throws BeanException {
224         throw new BeanException("Operation not supported except in IndexedBeanProperty");
225     }
226
227     /**
228      * Sets the value of the Java bean property to the given value
229      *
230      * @param bean The instance of the Java bean to set the property on
231      * @param value The value to set the property to
232      * @param convert Determines whether or not value should be converted
233      * to the type that the setter requires or not
234      * @throws BeanException If there was an error setting the Java bean property or
235      * the setter method threw a checked Exception
236      * @throws TypeConversionException If there was a problem auto-converting the
237      * property value
238      */

239     public void setPropertyValue(final Object JavaDoc bean, Object JavaDoc value,
240             final boolean convert)
241     throws BeanException, TypeConversionException {
242
243         // If we are autoConverting, convert the parameter
244
if (convert) {
245             value = convertParameter(value, bean, propertyType);
246         }
247
248         // Store the old value if there are property listeners
249
Object JavaDoc oldValue = null;
250
251         if (hasPropertyListeners()) {
252             oldValue = JavaBeanTools.callGetter(this, bean);
253         }
254
255         JavaBeanTools.callSetter(this, bean, value);
256
257         if (hasPropertyListeners()) {
258             firePropertyEvent(SET, oldValue, value, bean, null);
259         }
260     }
261 }
Popular Tags