KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > beans > IndexedPropertyDescriptor


1 /*
2  * @(#)IndexedPropertyDescriptor.java 1.49 04/05/05
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.beans;
9
10 import java.lang.ref.Reference JavaDoc;
11
12 import java.lang.reflect.Method JavaDoc;
13
14 /**
15  * An IndexedPropertyDescriptor describes a property that acts like an
16  * array and has an indexed read and/or indexed write method to access
17  * specific elements of the array.
18  * <p>
19  * An indexed property may also provide simple non-indexed read and write
20  * methods. If these are present, they read and write arrays of the type
21  * returned by the indexed read method.
22  */

23
24 public class IndexedPropertyDescriptor extends PropertyDescriptor JavaDoc {
25
26     private Reference JavaDoc indexedPropertyTypeRef;
27     private Reference JavaDoc indexedReadMethodRef;
28     private Reference JavaDoc indexedWriteMethodRef;
29
30     private String JavaDoc indexedReadMethodName;
31     private String JavaDoc indexedWriteMethodName;
32
33     /**
34      * This constructor constructs an IndexedPropertyDescriptor for a property
35      * that follows the standard Java conventions by having getFoo and setFoo
36      * accessor methods, for both indexed access and array access.
37      * <p>
38      * Thus if the argument name is "fred", it will assume that there
39      * is an indexed reader method "getFred", a non-indexed (array) reader
40      * method also called "getFred", an indexed writer method "setFred",
41      * and finally a non-indexed writer method "setFred".
42      *
43      * @param propertyName The programmatic name of the property.
44      * @param beanClass The Class object for the target bean.
45      * @exception IntrospectionException if an exception occurs during
46      * introspection.
47      */

48     public IndexedPropertyDescriptor(String JavaDoc propertyName, Class JavaDoc<?> beanClass)
49         throws IntrospectionException JavaDoc {
50     this(propertyName, beanClass,
51              "get" + capitalize(propertyName),
52              "set" + capitalize(propertyName),
53              "get" + capitalize(propertyName),
54              "set" + capitalize(propertyName));
55     }
56
57     /**
58      * This constructor takes the name of a simple property, and method
59      * names for reading and writing the property, both indexed
60      * and non-indexed.
61      *
62      * @param propertyName The programmatic name of the property.
63      * @param beanClass The Class object for the target bean.
64      * @param readMethodName The name of the method used for reading the property
65      * values as an array. May be null if the property is write-only
66      * or must be indexed.
67      * @param writeMethodName The name of the method used for writing the property
68      * values as an array. May be null if the property is read-only
69      * or must be indexed.
70      * @param indexedReadMethodName The name of the method used for reading
71      * an indexed property value.
72      * May be null if the property is write-only.
73      * @param indexedWriteMethodName The name of the method used for writing
74      * an indexed property value.
75      * May be null if the property is read-only.
76      * @exception IntrospectionException if an exception occurs during
77      * introspection.
78      */

79     public IndexedPropertyDescriptor(String JavaDoc propertyName, Class JavaDoc<?> beanClass,
80         String JavaDoc readMethodName, String JavaDoc writeMethodName,
81         String JavaDoc indexedReadMethodName, String JavaDoc indexedWriteMethodName)
82         throws IntrospectionException JavaDoc {
83     super(propertyName, beanClass, readMethodName, writeMethodName);
84
85     this.indexedReadMethodName = indexedReadMethodName;
86     if (indexedReadMethodName != null && getIndexedReadMethod() == null) {
87         throw new IntrospectionException JavaDoc("Method not found: " + indexedReadMethodName);
88     }
89
90     this.indexedWriteMethodName = indexedWriteMethodName;
91     if (indexedWriteMethodName != null && getIndexedWriteMethod() == null) {
92         throw new IntrospectionException JavaDoc("Method not found: " + indexedWriteMethodName);
93     }
94     // Implemented only for type checking.
95
findIndexedPropertyType(getIndexedReadMethod(), getIndexedWriteMethod());
96     }
97
98     /**
99      * This constructor takes the name of a simple property, and Method
100      * objects for reading and writing the property.
101      *
102      * @param propertyName The programmatic name of the pro
103 perty.
104      * @param readMethod The method used for reading the property values as an array.
105      * May be null if the property is write-only or must be indexed.
106      * @param writeMethod The method used for writing the property values as an array.
107      * May be null if the property is read-only or must be indexed.
108      * @param indexedReadMethod The method used for reading an indexed property value.
109      * May be null if the property is write-only.
110      * @param indexedWriteMethod The method used for writing an indexed property value.
111      * May be null if the property is read-only.
112      * @exception IntrospectionException if an exception occurs during
113      * introspection.
114      */

115     public IndexedPropertyDescriptor(String JavaDoc propertyName, Method JavaDoc readMethod, Method JavaDoc writeMethod,
116                         Method JavaDoc indexedReadMethod, Method JavaDoc indexedWriteMethod)
117         throws IntrospectionException JavaDoc {
118     super(propertyName, readMethod, writeMethod);
119
120     setIndexedReadMethod0(indexedReadMethod);
121     setIndexedWriteMethod0(indexedWriteMethod);
122
123     // Type checking
124
setIndexedPropertyType(findIndexedPropertyType(indexedReadMethod, indexedWriteMethod));
125     }
126     
127     /**
128      * Gets the method that should be used to read an indexed
129      * property value.
130      *
131      * @return The method that should be used to read an indexed
132      * property value.
133      * May return null if the property isn't indexed or is write-only.
134      */

135     public synchronized Method JavaDoc getIndexedReadMethod() {
136     Method JavaDoc indexedReadMethod = getIndexedReadMethod0();
137     if (indexedReadMethod == null) {
138         Class JavaDoc cls = getClass0();
139         if (cls == null ||
140         (indexedReadMethodName == null && indexedReadMethodRef == null)) {
141         // the Indexed readMethod was explicitly set to null.
142
return null;
143         }
144         if (indexedReadMethodName == null) {
145         Class JavaDoc type = getIndexedPropertyType0();
146         if (type == boolean.class || type == null) {
147             indexedReadMethodName = "is" + getBaseName();
148         } else {
149             indexedReadMethodName = "get" + getBaseName();
150         }
151         }
152         
153         Class JavaDoc[] args = { int.class };
154         
155         indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName,
156                             1, args);
157         if (indexedReadMethod == null) {
158         // no "is" method, so look for a "get" method.
159
indexedReadMethodName = "get" + getBaseName();
160         indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName,
161                                 1, args);
162         }
163         setIndexedReadMethod0(indexedReadMethod);
164     }
165     return indexedReadMethod;
166     }
167
168     /**
169      * Sets the method that should be used to read an indexed property value.
170      *
171      * @param readMethod The new indexed read method.
172      */

173     public synchronized void setIndexedReadMethod(Method JavaDoc readMethod)
174     throws IntrospectionException JavaDoc {
175
176     // the indexed property type is set by the reader.
177
setIndexedPropertyType(findIndexedPropertyType(readMethod,
178                                getIndexedWriteMethod0()));
179     setIndexedReadMethod0(readMethod);
180     }
181
182     private void setIndexedReadMethod0(Method JavaDoc readMethod) {
183     if (readMethod == null) {
184         indexedReadMethodName = null;
185         indexedReadMethodRef = null;
186         return;
187     }
188     setClass0(readMethod.getDeclaringClass());
189
190     indexedReadMethodName = readMethod.getName();
191     indexedReadMethodRef = createReference(readMethod);
192     }
193
194
195     /**
196      * Gets the method that should be used to write an indexed property value.
197      *
198      * @return The method that should be used to write an indexed
199      * property value.
200      * May return null if the property isn't indexed or is read-only.
201      */

202     public synchronized Method JavaDoc getIndexedWriteMethod() {
203     Method JavaDoc indexedWriteMethod = getIndexedWriteMethod0();
204     if (indexedWriteMethod == null) {
205         Class JavaDoc cls = getClass0();
206         if (cls == null ||
207         (indexedWriteMethodName == null && indexedWriteMethodRef == null)) {
208         // the Indexed writeMethod was explicitly set to null.
209
return null;
210         }
211
212         // We need the indexed type to ensure that we get the correct method.
213
// Cannot use the getIndexedPropertyType method since that could
214
// result in an infinite loop.
215
Class JavaDoc type = getIndexedPropertyType0();
216         if (type == null) {
217         try {
218             type = findIndexedPropertyType(getIndexedReadMethod(), null);
219             setIndexedPropertyType(type);
220         } catch (IntrospectionException JavaDoc ex) {
221             // Set iprop type to be the classic type
222
Class JavaDoc propType = getPropertyType();
223             if (propType.isArray()) {
224             type = propType.getComponentType();
225             }
226         }
227         }
228         
229         if (indexedWriteMethodName == null) {
230         indexedWriteMethodName = "set" + getBaseName();
231         }
232         indexedWriteMethod = Introspector.findMethod(cls, indexedWriteMethodName,
233              2, (type == null) ? null : new Class JavaDoc[] { int.class, type });
234         setIndexedWriteMethod0(indexedWriteMethod);
235     }
236     return indexedWriteMethod;
237     }
238
239     /**
240      * Sets the method that should be used to write an indexed property value.
241      *
242      * @param writeMethod The new indexed write method.
243      */

244     public synchronized void setIndexedWriteMethod(Method JavaDoc writeMethod)
245     throws IntrospectionException JavaDoc {
246
247     // If the indexed property type has not been set, then set it.
248
Class JavaDoc type = findIndexedPropertyType(getIndexedReadMethod(),
249                          writeMethod);
250     setIndexedPropertyType(type);
251     setIndexedWriteMethod0(writeMethod);
252     }
253
254     private void setIndexedWriteMethod0(Method JavaDoc writeMethod) {
255     if (writeMethod == null) {
256         indexedWriteMethodName = null;
257         indexedWriteMethodRef = null;
258         return;
259     }
260     setClass0(writeMethod.getDeclaringClass());
261
262     indexedWriteMethodName = writeMethod.getName();
263     indexedWriteMethodRef = createReference(writeMethod);
264     }
265
266     /**
267      * Gets the <code>Class</code> object of the indexed properties' type.
268      * The returned <code>Class</code> may describe a primitive type such as <code>int</code>.
269      *
270      * @return The <code>Class</code> for the indexed properties' type; may return <code>null</code>
271      * if the type cannot be determined.
272      */

273     public synchronized Class JavaDoc<?> getIndexedPropertyType() {
274     Class JavaDoc type = getIndexedPropertyType0();
275     if (type == null) {
276         try {
277         type = findIndexedPropertyType(getIndexedReadMethod(),
278                            getIndexedWriteMethod());
279         setIndexedPropertyType(type);
280         } catch (IntrospectionException JavaDoc ex) {
281         // fall
282
}
283     }
284     return type;
285     }
286
287     // Private methods which set get/set the Reference objects
288

289     private void setIndexedPropertyType(Class JavaDoc type) {
290     indexedPropertyTypeRef = createReference(type);
291     }
292
293     private Class JavaDoc getIndexedPropertyType0() {
294     return (Class JavaDoc)getObject(indexedPropertyTypeRef);
295     }
296
297     private Method JavaDoc getIndexedReadMethod0() {
298     return (Method JavaDoc)getObject(indexedReadMethodRef);
299     }
300
301     private Method JavaDoc getIndexedWriteMethod0() {
302     return (Method JavaDoc)getObject(indexedWriteMethodRef);
303     }
304
305     private Class JavaDoc findIndexedPropertyType(Method JavaDoc indexedReadMethod,
306                       Method JavaDoc indexedWriteMethod)
307     throws IntrospectionException JavaDoc {
308     Class JavaDoc indexedPropertyType = null;
309
310     if (indexedReadMethod != null) {
311         Class JavaDoc params[] = indexedReadMethod.getParameterTypes();
312         if (params.length != 1) {
313         throw new IntrospectionException JavaDoc("bad indexed read method arg count");
314         }
315         if (params[0] != Integer.TYPE) {
316         throw new IntrospectionException JavaDoc("non int index to indexed read method");
317         }
318         indexedPropertyType = indexedReadMethod.getReturnType();
319         if (indexedPropertyType == Void.TYPE) {
320         throw new IntrospectionException JavaDoc("indexed read method returns void");
321         }
322     }
323     if (indexedWriteMethod != null) {
324         Class JavaDoc params[] = indexedWriteMethod.getParameterTypes();
325         if (params.length != 2) {
326         throw new IntrospectionException JavaDoc("bad indexed write method arg count");
327         }
328         if (params[0] != Integer.TYPE) {
329         throw new IntrospectionException JavaDoc("non int index to indexed write method");
330         }
331         if (indexedPropertyType != null && indexedPropertyType != params[1]) {
332         throw new IntrospectionException JavaDoc(
333                          "type mismatch between indexed read and indexed write methods: "
334                          + getName());
335         }
336         indexedPropertyType = params[1];
337     }
338     Class JavaDoc propertyType = getPropertyType();
339     if (propertyType != null && (!propertyType.isArray() ||
340                      propertyType.getComponentType() != indexedPropertyType)) {
341         throw new IntrospectionException JavaDoc("type mismatch between indexed and non-indexed methods: "
342                          + getName());
343     }
344     return indexedPropertyType;
345     }
346
347     /**
348      * Compares this <code>PropertyDescriptor</code> against the specified object.
349      * Returns true if the objects are the same. Two <code>PropertyDescriptor</code>s
350      * are the same if the read, write, property types, property editor and
351      * flags are equivalent.
352      *
353      * @since 1.4
354      */

355     public boolean equals(Object JavaDoc obj) {
356     // Note: This would be identical to PropertyDescriptor but they don't
357
// share the same fields.
358
if (this == obj) {
359         return true;
360     }
361
362     if (obj != null && obj instanceof IndexedPropertyDescriptor JavaDoc) {
363         IndexedPropertyDescriptor JavaDoc other = (IndexedPropertyDescriptor JavaDoc)obj;
364         Method JavaDoc otherIndexedReadMethod = other.getIndexedReadMethod();
365         Method JavaDoc otherIndexedWriteMethod = other.getIndexedWriteMethod();
366
367         if (!compareMethods(getIndexedReadMethod(), otherIndexedReadMethod)) {
368         return false;
369         }
370
371         if (!compareMethods(getIndexedWriteMethod(), otherIndexedWriteMethod)) {
372         return false;
373         }
374
375         if (getIndexedPropertyType() != other.getIndexedPropertyType()) {
376         return false;
377         }
378         return super.equals(obj);
379     }
380     return false;
381     }
382
383     /**
384      * Package-private constructor.
385      * Merge two property descriptors. Where they conflict, give the
386      * second argument (y) priority over the first argumnnt (x).
387      *
388      * @param x The first (lower priority) PropertyDescriptor
389      * @param y The second (higher priority) PropertyDescriptor
390      */

391
392     IndexedPropertyDescriptor(PropertyDescriptor JavaDoc x, PropertyDescriptor JavaDoc y) {
393     super(x,y);
394     if (x instanceof IndexedPropertyDescriptor JavaDoc) {
395         IndexedPropertyDescriptor JavaDoc ix = (IndexedPropertyDescriptor JavaDoc)x;
396         try {
397         Method JavaDoc xr = ix.getIndexedReadMethod();
398         if (xr != null) {
399             setIndexedReadMethod(xr);
400         }
401         
402         Method JavaDoc xw = ix.getIndexedWriteMethod();
403         if (xw != null) {
404             setIndexedWriteMethod(xw);
405         }
406         } catch (IntrospectionException JavaDoc ex) {
407         // Should not happen
408
throw new AssertionError JavaDoc(ex);
409         }
410     }
411     if (y instanceof IndexedPropertyDescriptor JavaDoc) {
412         IndexedPropertyDescriptor JavaDoc iy = (IndexedPropertyDescriptor JavaDoc)y;
413         try {
414         Method JavaDoc yr = iy.getIndexedReadMethod();
415         if (yr != null && yr.getDeclaringClass() == getClass0()) {
416             setIndexedReadMethod(yr);
417         }
418         
419         Method JavaDoc yw = iy.getIndexedWriteMethod();
420         if (yw != null && yw.getDeclaringClass() == getClass0()) {
421             setIndexedWriteMethod(yw);
422         }
423         } catch (IntrospectionException JavaDoc ex) {
424         // Should not happen
425
throw new AssertionError JavaDoc(ex);
426         }
427     }
428     }
429
430     /*
431      * Package-private dup constructor
432      * This must isolate the new object from any changes to the old object.
433      */

434     IndexedPropertyDescriptor(IndexedPropertyDescriptor JavaDoc old) {
435     super(old);
436     indexedReadMethodRef = old.indexedReadMethodRef;
437     indexedWriteMethodRef = old.indexedWriteMethodRef;
438     indexedPropertyTypeRef = old.indexedPropertyTypeRef;
439     indexedWriteMethodName = old.indexedWriteMethodName;
440     indexedReadMethodName = old.indexedReadMethodName;
441     }
442
443     /**
444      * Returns a hash code value for the object.
445      * See {@link java.lang.Object#hashCode} for a complete description.
446      *
447      * @return a hash code value for this object.
448      * @since 1.5
449      */

450     public int hashCode() {
451     int result = super.hashCode();
452
453     result = 37 * result + ((indexedWriteMethodName == null) ? 0 :
454                 indexedWriteMethodName.hashCode());
455     result = 37 * result + ((indexedReadMethodName == null) ? 0 :
456                 indexedReadMethodName.hashCode());
457     result = 37 * result + ((getIndexedPropertyType() == null) ? 0 :
458                 getIndexedPropertyType().hashCode());
459     
460     return result;
461     }
462
463     /*
464     public String toString() {
465     String message = super.toString();
466
467     message += ", indexedType=";
468     message += getIndexedPropertyType();
469
470     message += ", indexedWriteMethod=";
471     message += indexedWriteMethodName;
472
473     message += ", indexedReadMethod=";
474     message += indexedReadMethodName;
475     
476     return message;
477     }
478     */

479 }
480
Popular Tags