API Overview API Index Package Overview Direct link to this page
JDK 1.6
  java.beans. IndexedPropertyDescriptor View Javadoc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479

/*
 * @(#)IndexedPropertyDescriptor.java	1.50 05/11/17
 *
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package java.beans;

import java.lang.ref.Reference;

import java.lang.reflect.Method;

/**
 * An IndexedPropertyDescriptor describes a property that acts like an
 * array and has an indexed read and/or indexed write method to access
 * specific elements of the array.
 * <p>
 * An indexed property may also provide simple non-indexed read and write
 * methods.  If these are present, they read and write arrays of the type
 * returned by the indexed read method.
 */

public class IndexedPropertyDescriptor extends PropertyDescriptor {

    private Reference indexedPropertyTypeRef;
    private Reference indexedReadMethodRef;
    private Reference indexedWriteMethodRef;

    private String indexedReadMethodName;
    private String indexedWriteMethodName;

    /**
     * This constructor constructs an IndexedPropertyDescriptor for a property
     * that follows the standard Java conventions by having getFoo and setFoo 
     * accessor methods, for both indexed access and array access.
     * <p>
     * Thus if the argument name is "fred", it will assume that there
     * is an indexed reader method "getFred", a non-indexed (array) reader
     * method also called "getFred", an indexed writer method "setFred",
     * and finally a non-indexed writer method "setFred".
     *
     * @param propertyName The programmatic name of the property.
     * @param beanClass The Class object for the target bean.
     * @exception IntrospectionException if an exception occurs during
     *              introspection.
     */
    public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass)
		throws IntrospectionException {
	this(propertyName, beanClass,
			 "get" + capitalize(propertyName),
			 "set" + capitalize(propertyName),
			 "get" + capitalize(propertyName),
			 "set" + capitalize(propertyName));
    }

    /**
     * This constructor takes the name of a simple property, and method
     * names for reading and writing the property, both indexed
     * and non-indexed.
     *
     * @param propertyName The programmatic name of the property.
     * @param beanClass  The Class object for the target bean.
     * @param readMethodName The name of the method used for reading the property
     *		 values as an array.  May be null if the property is write-only
     *		 or must be indexed.
     * @param writeMethodName The name of the method used for writing the property
     *		 values as an array.  May be null if the property is read-only
     *		 or must be indexed.
     * @param indexedReadMethodName The name of the method used for reading
     *		an indexed property value.
     *		May be null if the property is write-only.
     * @param indexedWriteMethodName The name of the method used for writing
     *		an indexed property value.  
     *		May be null if the property is read-only.
     * @exception IntrospectionException if an exception occurs during
     *              introspection.
     */
    public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass,
		String readMethodName, String writeMethodName,
		String indexedReadMethodName, String indexedWriteMethodName)
		throws IntrospectionException {
	super(propertyName, beanClass, readMethodName, writeMethodName);

	this.indexedReadMethodName = indexedReadMethodName;
	if (indexedReadMethodName != null && getIndexedReadMethod() == null) {
	    throw new IntrospectionException("Method not found: " + indexedReadMethodName);
	}

	this.indexedWriteMethodName = indexedWriteMethodName;
	if (indexedWriteMethodName != null && getIndexedWriteMethod() == null) {
	    throw new IntrospectionException("Method not found: " + indexedWriteMethodName);
	}
	// Implemented only for type checking.
	findIndexedPropertyType(getIndexedReadMethod(), getIndexedWriteMethod());
    }

    /**
     * This constructor takes the name of a simple property, and Method
     * objects for reading and writing the property.
     *
     * @param propertyName The programmatic name of the pro
perty.
     * @param readMethod The method used for reading the property values as an array.
     *		May be null if the property is write-only or must be indexed.
     * @param writeMethod The method used for writing the property values as an array.
     *		May be null if the property is read-only or must be indexed.
     * @param indexedReadMethod The method used for reading an indexed property value.
     *		May be null if the property is write-only.
     * @param indexedWriteMethod The method used for writing an indexed property value.  
     *		May be null if the property is read-only.
     * @exception IntrospectionException if an exception occurs during
     *              introspection.
     */
    public IndexedPropertyDescriptor(String propertyName, Method readMethod, Method writeMethod,
 					    Method indexedReadMethod, Method indexedWriteMethod)
		throws IntrospectionException {
	super(propertyName, readMethod, writeMethod);

	setIndexedReadMethod0(indexedReadMethod);
	setIndexedWriteMethod0(indexedWriteMethod);

	// Type checking
	setIndexedPropertyType(findIndexedPropertyType(indexedReadMethod, indexedWriteMethod));
    }
    
    /**
     * Gets the method that should be used to read an indexed
     * property value.
     *
     * @return The method that should be used to read an indexed
     * property value.
     * May return null if the property isn't indexed or is write-only.
     */
    public synchronized Method getIndexedReadMethod() {
	Method indexedReadMethod = getIndexedReadMethod0();
	if (indexedReadMethod == null) {
	    Class cls = getClass0();
	    if (cls == null || 
		(indexedReadMethodName == null && indexedReadMethodRef == null)) {
		// the Indexed readMethod was explicitly set to null.
		return null;
	    }
	    if (indexedReadMethodName == null) {
		Class type = getIndexedPropertyType0();
		if (type == boolean.class || type == null) {
		    indexedReadMethodName = "is" + getBaseName();
		} else {
		    indexedReadMethodName = "get" + getBaseName();
		}
	    }
	    
	    Class[] args = { int.class };
	    
	    indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 
							1, args);
	    if (indexedReadMethod == null) {
		// no "is" method, so look for a "get" method.
		indexedReadMethodName = "get" + getBaseName();
		indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 
							    1, args);
	    }
	    setIndexedReadMethod0(indexedReadMethod);
	}
	return indexedReadMethod;
    }

    /**
     * Sets the method that should be used to read an indexed property value.
     *
     * @param readMethod The new indexed read method.
     */
    public synchronized void setIndexedReadMethod(Method readMethod) 
	throws IntrospectionException {

	// the indexed property type is set by the reader.
	setIndexedPropertyType(findIndexedPropertyType(readMethod, 
						       getIndexedWriteMethod0()));
	setIndexedReadMethod0(readMethod);
    }

    private void setIndexedReadMethod0(Method readMethod) {
	if (readMethod == null) {
	    indexedReadMethodName = null;
	    indexedReadMethodRef = null;
	    return;
	}
	setClass0(readMethod.getDeclaringClass());

	indexedReadMethodName = readMethod.getName();
	indexedReadMethodRef = createReference(readMethod);
    }


    /**
     * Gets the method that should be used to write an indexed property value.
     *
     * @return The method that should be used to write an indexed
     * property value.
     * May return null if the property isn't indexed or is read-only.
     */
    public synchronized Method getIndexedWriteMethod() {
	Method indexedWriteMethod = getIndexedWriteMethod0();
	if (indexedWriteMethod == null) {
	    Class cls = getClass0();
	    if (cls == null || 
		(indexedWriteMethodName == null && indexedWriteMethodRef == null)) {
		// the Indexed writeMethod was explicitly set to null.
		return null;
	    }

	    // We need the indexed type to ensure that we get the correct method.
	    // Cannot use the getIndexedPropertyType method since that could 
	    // result in an infinite loop.
	    Class type = getIndexedPropertyType0();
	    if (type == null) {
		try {
		    type = findIndexedPropertyType(getIndexedReadMethod(), null);
		    setIndexedPropertyType(type);
		} catch (IntrospectionException ex) {
		    // Set iprop type to be the classic type
		    Class propType = getPropertyType();
		    if (propType.isArray()) {
			type = propType.getComponentType();
		    }
		}
	    }
		
	    if (indexedWriteMethodName == null) {
		indexedWriteMethodName = "set" + getBaseName();
	    }
	    indexedWriteMethod = Introspector.findMethod(cls, indexedWriteMethodName, 
			 2, (type == null) ? null : new Class[] { int.class, type });
	    setIndexedWriteMethod0(indexedWriteMethod);
	}
	return indexedWriteMethod;
    }

    /**
     * Sets the method that should be used to write an indexed property value.
     *
     * @param writeMethod The new indexed write method.
     */
    public synchronized void setIndexedWriteMethod(Method writeMethod) 
	throws IntrospectionException {

	// If the indexed property type has not been set, then set it.
	Class type = findIndexedPropertyType(getIndexedReadMethod(), 
					     writeMethod);
	setIndexedPropertyType(type);
	setIndexedWriteMethod0(writeMethod);
    }

    private void setIndexedWriteMethod0(Method writeMethod) {
	if (writeMethod == null) {
	    indexedWriteMethodName = null;
	    indexedWriteMethodRef = null;
	    return;
	}
	setClass0(writeMethod.getDeclaringClass());

	indexedWriteMethodName = writeMethod.getName();
	indexedWriteMethodRef = createReference(writeMethod);
    }

    /**
     * Gets the <code>Class</code> object of the indexed properties' type.
     * The returned <code>Class</code> may describe a primitive type such as <code>int</code>.
     *
     * @return The <code>Class</code> for the indexed properties' type; may return <code>null</code>
     *         if the type cannot be determined.
     */
    public synchronized Class<?> getIndexedPropertyType() {
	Class type = getIndexedPropertyType0();
	if (type == null) {
	    try {
		type = findIndexedPropertyType(getIndexedReadMethod(), 
					       getIndexedWriteMethod());
		setIndexedPropertyType(type);
	    } catch (IntrospectionException ex) {
		// fall
	    }
	}
	return type;
    }

    // Private methods which set get/set the Reference objects

    private void setIndexedPropertyType(Class type) {
	indexedPropertyTypeRef = createReference(type);
    }

    private Class getIndexedPropertyType0() {
	return (Class)getObject(indexedPropertyTypeRef);
    }

    private Method getIndexedReadMethod0() {
	return (Method)getObject(indexedReadMethodRef);
    }

    private Method getIndexedWriteMethod0() {
	return (Method)getObject(indexedWriteMethodRef);
    }

    private Class findIndexedPropertyType(Method indexedReadMethod,
					  Method indexedWriteMethod) 
	throws IntrospectionException {
	Class indexedPropertyType = null;

	if (indexedReadMethod != null) {
	    Class params[] = indexedReadMethod.getParameterTypes();
	    if (params.length != 1) {
		throw new IntrospectionException("bad indexed read method arg count");
	    }
	    if (params[0] != Integer.TYPE) {
		throw new IntrospectionException("non int index to indexed read method");
	    }
	    indexedPropertyType = indexedReadMethod.getReturnType();
	    if (indexedPropertyType == Void.TYPE) {
		throw new IntrospectionException("indexed read method returns void");
	    }
	}
	if (indexedWriteMethod != null) {
	    Class params[] = indexedWriteMethod.getParameterTypes();
	    if (params.length != 2) {
		throw new IntrospectionException("bad indexed write method arg count");
	    }
	    if (params[0] != Integer.TYPE) {
		throw new IntrospectionException("non int index to indexed write method");
	    }
	    if (indexedPropertyType != null && indexedPropertyType != params[1]) {
		throw new IntrospectionException(
						 "type mismatch between indexed read and indexed write methods: " 
						 + getName());
	    }
	    indexedPropertyType = params[1];
	}
	Class propertyType = getPropertyType();
	if (propertyType != null && (!propertyType.isArray() ||
				     propertyType.getComponentType() != indexedPropertyType)) {
	    throw new IntrospectionException("type mismatch between indexed and non-indexed methods: " 
					     + getName());
	}
	return indexedPropertyType;
    }

    /**
     * Compares this <code>PropertyDescriptor</code> against the specified object.
     * Returns true if the objects are the same. Two <code>PropertyDescriptor</code>s
     * are the same if the read, write, property types, property editor and
     * flags  are equivalent.
     *
     * @since 1.4
     */
    public boolean equals(Object obj) {
	// Note: This would be identical to PropertyDescriptor but they don't
	// share the same fields.
	if (this == obj) {
	    return true;
	}

	if (obj != null && obj instanceof IndexedPropertyDescriptor) {
	    IndexedPropertyDescriptor other = (IndexedPropertyDescriptor)obj;
	    Method otherIndexedReadMethod = other.getIndexedReadMethod();
	    Method otherIndexedWriteMethod = other.getIndexedWriteMethod();

	    if (!compareMethods(getIndexedReadMethod(), otherIndexedReadMethod)) {
		return false;
	    }

	    if (!compareMethods(getIndexedWriteMethod(), otherIndexedWriteMethod)) {
		return false;
	    }

	    if (getIndexedPropertyType() != other.getIndexedPropertyType()) {
		return false;
	    }
	    return super.equals(obj);
	}
	return false;
    }

    /**
     * Package-private constructor.
     * Merge two property descriptors.  Where they conflict, give the
     * second argument (y) priority over the first argumnnt (x).
     *
     * @param x  The first (lower priority) PropertyDescriptor
     * @param y  The second (higher priority) PropertyDescriptor
     */

    IndexedPropertyDescriptor(PropertyDescriptor x, PropertyDescriptor y) {
	super(x,y);
	if (x instanceof IndexedPropertyDescriptor) {
	    IndexedPropertyDescriptor ix = (IndexedPropertyDescriptor)x;
	    try {
		Method xr = ix.getIndexedReadMethod();
		if (xr != null) {
		    setIndexedReadMethod(xr);
		}
		
		Method xw = ix.getIndexedWriteMethod();
		if (xw != null) {
		    setIndexedWriteMethod(xw);
		}
	    } catch (IntrospectionException ex) {
		// Should not happen
		throw new AssertionError(ex);
	    }
	}
	if (y instanceof IndexedPropertyDescriptor) {
	    IndexedPropertyDescriptor iy = (IndexedPropertyDescriptor)y;
	    try {
		Method yr = iy.getIndexedReadMethod();
		if (yr != null && yr.getDeclaringClass() == getClass0()) {
		    setIndexedReadMethod(yr);
		}
		
		Method yw = iy.getIndexedWriteMethod();
		if (yw != null && yw.getDeclaringClass() == getClass0()) {
		    setIndexedWriteMethod(yw);
		}
	    } catch (IntrospectionException ex) {
		// Should not happen
		throw new AssertionError(ex);
	    }
	}
    }

    /*
     * Package-private dup constructor
     * This must isolate the new object from any changes to the old object.
     */
    IndexedPropertyDescriptor(IndexedPropertyDescriptor old) {
	super(old);
	indexedReadMethodRef = old.indexedReadMethodRef;
	indexedWriteMethodRef = old.indexedWriteMethodRef;
	indexedPropertyTypeRef = old.indexedPropertyTypeRef;
	indexedWriteMethodName = old.indexedWriteMethodName;
	indexedReadMethodName = old.indexedReadMethodName;
    }

    /**
     * Returns a hash code value for the object. 
     * See {@link java.lang.Object#hashCode} for a complete description.
     *
     * @return a hash code value for this object.
     * @since 1.5
     */
    public int hashCode() {
	int result = super.hashCode();

	result = 37 * result + ((indexedWriteMethodName == null) ? 0 : 
				indexedWriteMethodName.hashCode());
	result = 37 * result + ((indexedReadMethodName == null) ? 0 : 
				indexedReadMethodName.hashCode());
	result = 37 * result + ((getIndexedPropertyType() == null) ? 0 : 
				getIndexedPropertyType().hashCode());
	
	return result;
    }

    /*
    public String toString() {
	String message = super.toString();

	message += ", indexedType=";
	message += getIndexedPropertyType();

	message += ", indexedWriteMethod=";
	message += indexedWriteMethodName;

	message += ", indexedReadMethod=";
	message += indexedReadMethodName;
	
	return message;
    }
    */
}

Generated By: JavaOnTracks Doclet 0.1.4     ©Thibaut Colar