Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java
38829 views
1
/*
2
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package java.beans;
27
28
import java.lang.ref.Reference;
29
import java.lang.reflect.Method;
30
31
/**
32
* An IndexedPropertyDescriptor describes a property that acts like an
33
* array and has an indexed read and/or indexed write method to access
34
* specific elements of the array.
35
* <p>
36
* An indexed property may also provide simple non-indexed read and write
37
* methods. If these are present, they read and write arrays of the type
38
* returned by the indexed read method.
39
*/
40
41
public class IndexedPropertyDescriptor extends PropertyDescriptor {
42
43
private Reference<? extends Class<?>> indexedPropertyTypeRef;
44
private final MethodRef indexedReadMethodRef = new MethodRef();
45
private final MethodRef indexedWriteMethodRef = new MethodRef();
46
47
private String indexedReadMethodName;
48
private String indexedWriteMethodName;
49
50
/**
51
* This constructor constructs an IndexedPropertyDescriptor for a property
52
* that follows the standard Java conventions by having getFoo and setFoo
53
* accessor methods, for both indexed access and array access.
54
* <p>
55
* Thus if the argument name is "fred", it will assume that there
56
* is an indexed reader method "getFred", a non-indexed (array) reader
57
* method also called "getFred", an indexed writer method "setFred",
58
* and finally a non-indexed writer method "setFred".
59
*
60
* @param propertyName The programmatic name of the property.
61
* @param beanClass The Class object for the target bean.
62
* @exception IntrospectionException if an exception occurs during
63
* introspection.
64
*/
65
public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass)
66
throws IntrospectionException {
67
this(propertyName, beanClass,
68
Introspector.GET_PREFIX + NameGenerator.capitalize(propertyName),
69
Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName),
70
Introspector.GET_PREFIX + NameGenerator.capitalize(propertyName),
71
Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName));
72
}
73
74
/**
75
* This constructor takes the name of a simple property, and method
76
* names for reading and writing the property, both indexed
77
* and non-indexed.
78
*
79
* @param propertyName The programmatic name of the property.
80
* @param beanClass The Class object for the target bean.
81
* @param readMethodName The name of the method used for reading the property
82
* values as an array. May be null if the property is write-only
83
* or must be indexed.
84
* @param writeMethodName The name of the method used for writing the property
85
* values as an array. May be null if the property is read-only
86
* or must be indexed.
87
* @param indexedReadMethodName The name of the method used for reading
88
* an indexed property value.
89
* May be null if the property is write-only.
90
* @param indexedWriteMethodName The name of the method used for writing
91
* an indexed property value.
92
* May be null if the property is read-only.
93
* @exception IntrospectionException if an exception occurs during
94
* introspection.
95
*/
96
public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass,
97
String readMethodName, String writeMethodName,
98
String indexedReadMethodName, String indexedWriteMethodName)
99
throws IntrospectionException {
100
super(propertyName, beanClass, readMethodName, writeMethodName);
101
102
this.indexedReadMethodName = indexedReadMethodName;
103
if (indexedReadMethodName != null && getIndexedReadMethod() == null) {
104
throw new IntrospectionException("Method not found: " + indexedReadMethodName);
105
}
106
107
this.indexedWriteMethodName = indexedWriteMethodName;
108
if (indexedWriteMethodName != null && getIndexedWriteMethod() == null) {
109
throw new IntrospectionException("Method not found: " + indexedWriteMethodName);
110
}
111
// Implemented only for type checking.
112
findIndexedPropertyType(getIndexedReadMethod(), getIndexedWriteMethod());
113
}
114
115
/**
116
* This constructor takes the name of a simple property, and Method
117
* objects for reading and writing the property.
118
*
119
* @param propertyName The programmatic name of the property.
120
* @param readMethod The method used for reading the property values as an array.
121
* May be null if the property is write-only or must be indexed.
122
* @param writeMethod The method used for writing the property values as an array.
123
* May be null if the property is read-only or must be indexed.
124
* @param indexedReadMethod The method used for reading an indexed property value.
125
* May be null if the property is write-only.
126
* @param indexedWriteMethod The method used for writing an indexed property value.
127
* May be null if the property is read-only.
128
* @exception IntrospectionException if an exception occurs during
129
* introspection.
130
*/
131
public IndexedPropertyDescriptor(String propertyName, Method readMethod, Method writeMethod,
132
Method indexedReadMethod, Method indexedWriteMethod)
133
throws IntrospectionException {
134
super(propertyName, readMethod, writeMethod);
135
136
setIndexedReadMethod0(indexedReadMethod);
137
setIndexedWriteMethod0(indexedWriteMethod);
138
139
// Type checking
140
setIndexedPropertyType(findIndexedPropertyType(indexedReadMethod, indexedWriteMethod));
141
}
142
143
/**
144
* Creates <code>PropertyDescriptor</code> for the specified bean
145
* with the specified name and methods to read/write the property value.
146
*
147
* @param bean the type of the target bean
148
* @param base the base name of the property (the rest of the method name)
149
* @param read the method used for reading the property value
150
* @param write the method used for writing the property value
151
* @param readIndexed the method used for reading an indexed property value
152
* @param writeIndexed the method used for writing an indexed property value
153
* @exception IntrospectionException if an exception occurs during introspection
154
*
155
* @since 1.7
156
*/
157
IndexedPropertyDescriptor(Class<?> bean, String base, Method read, Method write, Method readIndexed, Method writeIndexed) throws IntrospectionException {
158
super(bean, base, read, write);
159
160
setIndexedReadMethod0(readIndexed);
161
setIndexedWriteMethod0(writeIndexed);
162
163
// Type checking
164
setIndexedPropertyType(findIndexedPropertyType(readIndexed, writeIndexed));
165
}
166
167
/**
168
* Gets the method that should be used to read an indexed
169
* property value.
170
*
171
* @return The method that should be used to read an indexed
172
* property value.
173
* May return null if the property isn't indexed or is write-only.
174
*/
175
public synchronized Method getIndexedReadMethod() {
176
Method indexedReadMethod = this.indexedReadMethodRef.get();
177
if (indexedReadMethod == null) {
178
Class<?> cls = getClass0();
179
if (cls == null ||
180
(indexedReadMethodName == null && !this.indexedReadMethodRef.isSet())) {
181
// the Indexed readMethod was explicitly set to null.
182
return null;
183
}
184
String nextMethodName = Introspector.GET_PREFIX + getBaseName();
185
if (indexedReadMethodName == null) {
186
Class<?> type = getIndexedPropertyType0();
187
if (type == boolean.class || type == null) {
188
indexedReadMethodName = Introspector.IS_PREFIX + getBaseName();
189
} else {
190
indexedReadMethodName = nextMethodName;
191
}
192
}
193
194
Class<?>[] args = { int.class };
195
indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 1, args);
196
if ((indexedReadMethod == null) && !indexedReadMethodName.equals(nextMethodName)) {
197
// no "is" method, so look for a "get" method.
198
indexedReadMethodName = nextMethodName;
199
indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 1, args);
200
}
201
setIndexedReadMethod0(indexedReadMethod);
202
}
203
return indexedReadMethod;
204
}
205
206
/**
207
* Sets the method that should be used to read an indexed property value.
208
*
209
* @param readMethod The new indexed read method.
210
* @throws IntrospectionException if an exception occurs during
211
* introspection.
212
*/
213
public synchronized void setIndexedReadMethod(Method readMethod)
214
throws IntrospectionException {
215
216
// the indexed property type is set by the reader.
217
setIndexedPropertyType(findIndexedPropertyType(readMethod,
218
this.indexedWriteMethodRef.get()));
219
setIndexedReadMethod0(readMethod);
220
}
221
222
private void setIndexedReadMethod0(Method readMethod) {
223
this.indexedReadMethodRef.set(readMethod);
224
if (readMethod == null) {
225
indexedReadMethodName = null;
226
return;
227
}
228
setClass0(readMethod.getDeclaringClass());
229
230
indexedReadMethodName = readMethod.getName();
231
setTransient(readMethod.getAnnotation(Transient.class));
232
}
233
234
235
/**
236
* Gets the method that should be used to write an indexed property value.
237
*
238
* @return The method that should be used to write an indexed
239
* property value.
240
* May return null if the property isn't indexed or is read-only.
241
*/
242
public synchronized Method getIndexedWriteMethod() {
243
Method indexedWriteMethod = this.indexedWriteMethodRef.get();
244
if (indexedWriteMethod == null) {
245
Class<?> cls = getClass0();
246
if (cls == null ||
247
(indexedWriteMethodName == null && !this.indexedWriteMethodRef.isSet())) {
248
// the Indexed writeMethod was explicitly set to null.
249
return null;
250
}
251
252
// We need the indexed type to ensure that we get the correct method.
253
// Cannot use the getIndexedPropertyType method since that could
254
// result in an infinite loop.
255
Class<?> type = getIndexedPropertyType0();
256
if (type == null) {
257
try {
258
type = findIndexedPropertyType(getIndexedReadMethod(), null);
259
setIndexedPropertyType(type);
260
} catch (IntrospectionException ex) {
261
// Set iprop type to be the classic type
262
Class<?> propType = getPropertyType();
263
if (propType.isArray()) {
264
type = propType.getComponentType();
265
}
266
}
267
}
268
269
if (indexedWriteMethodName == null) {
270
indexedWriteMethodName = Introspector.SET_PREFIX + getBaseName();
271
}
272
273
Class<?>[] args = (type == null) ? null : new Class<?>[] { int.class, type };
274
indexedWriteMethod = Introspector.findMethod(cls, indexedWriteMethodName, 2, args);
275
if (indexedWriteMethod != null) {
276
if (!indexedWriteMethod.getReturnType().equals(void.class)) {
277
indexedWriteMethod = null;
278
}
279
}
280
setIndexedWriteMethod0(indexedWriteMethod);
281
}
282
return indexedWriteMethod;
283
}
284
285
/**
286
* Sets the method that should be used to write an indexed property value.
287
*
288
* @param writeMethod The new indexed write method.
289
* @throws IntrospectionException if an exception occurs during
290
* introspection.
291
*/
292
public synchronized void setIndexedWriteMethod(Method writeMethod)
293
throws IntrospectionException {
294
295
// If the indexed property type has not been set, then set it.
296
Class<?> type = findIndexedPropertyType(getIndexedReadMethod(),
297
writeMethod);
298
setIndexedPropertyType(type);
299
setIndexedWriteMethod0(writeMethod);
300
}
301
302
private void setIndexedWriteMethod0(Method writeMethod) {
303
this.indexedWriteMethodRef.set(writeMethod);
304
if (writeMethod == null) {
305
indexedWriteMethodName = null;
306
return;
307
}
308
setClass0(writeMethod.getDeclaringClass());
309
310
indexedWriteMethodName = writeMethod.getName();
311
setTransient(writeMethod.getAnnotation(Transient.class));
312
}
313
314
/**
315
* Returns the Java type info for the indexed property.
316
* Note that the {@code Class} object may describe
317
* primitive Java types such as {@code int}.
318
* This type is returned by the indexed read method
319
* or is used as the parameter type of the indexed write method.
320
*
321
* @return the {@code Class} object that represents the Java type info,
322
* or {@code null} if the type cannot be determined
323
*/
324
public synchronized Class<?> getIndexedPropertyType() {
325
Class<?> type = getIndexedPropertyType0();
326
if (type == null) {
327
try {
328
type = findIndexedPropertyType(getIndexedReadMethod(),
329
getIndexedWriteMethod());
330
setIndexedPropertyType(type);
331
} catch (IntrospectionException ex) {
332
// fall
333
}
334
}
335
return type;
336
}
337
338
// Private methods which set get/set the Reference objects
339
340
private void setIndexedPropertyType(Class<?> type) {
341
this.indexedPropertyTypeRef = getWeakReference(type);
342
}
343
344
private Class<?> getIndexedPropertyType0() {
345
return (this.indexedPropertyTypeRef != null)
346
? this.indexedPropertyTypeRef.get()
347
: null;
348
}
349
350
private Class<?> findIndexedPropertyType(Method indexedReadMethod,
351
Method indexedWriteMethod)
352
throws IntrospectionException {
353
Class<?> indexedPropertyType = null;
354
355
if (indexedReadMethod != null) {
356
Class params[] = getParameterTypes(getClass0(), indexedReadMethod);
357
if (params.length != 1) {
358
throw new IntrospectionException("bad indexed read method arg count");
359
}
360
if (params[0] != Integer.TYPE) {
361
throw new IntrospectionException("non int index to indexed read method");
362
}
363
indexedPropertyType = getReturnType(getClass0(), indexedReadMethod);
364
if (indexedPropertyType == Void.TYPE) {
365
throw new IntrospectionException("indexed read method returns void");
366
}
367
}
368
if (indexedWriteMethod != null) {
369
Class params[] = getParameterTypes(getClass0(), indexedWriteMethod);
370
if (params.length != 2) {
371
throw new IntrospectionException("bad indexed write method arg count");
372
}
373
if (params[0] != Integer.TYPE) {
374
throw new IntrospectionException("non int index to indexed write method");
375
}
376
if (indexedPropertyType == null || params[1].isAssignableFrom(indexedPropertyType)) {
377
indexedPropertyType = params[1];
378
} else if (!indexedPropertyType.isAssignableFrom(params[1])) {
379
throw new IntrospectionException(
380
"type mismatch between indexed read and indexed write methods: "
381
+ getName());
382
}
383
}
384
Class<?> propertyType = getPropertyType();
385
if (propertyType != null && (!propertyType.isArray() ||
386
propertyType.getComponentType() != indexedPropertyType)) {
387
throw new IntrospectionException("type mismatch between indexed and non-indexed methods: "
388
+ getName());
389
}
390
return indexedPropertyType;
391
}
392
393
/**
394
* Compares this <code>PropertyDescriptor</code> against the specified object.
395
* Returns true if the objects are the same. Two <code>PropertyDescriptor</code>s
396
* are the same if the read, write, property types, property editor and
397
* flags are equivalent.
398
*
399
* @since 1.4
400
*/
401
public boolean equals(Object obj) {
402
// Note: This would be identical to PropertyDescriptor but they don't
403
// share the same fields.
404
if (this == obj) {
405
return true;
406
}
407
408
if (obj != null && obj instanceof IndexedPropertyDescriptor) {
409
IndexedPropertyDescriptor other = (IndexedPropertyDescriptor)obj;
410
Method otherIndexedReadMethod = other.getIndexedReadMethod();
411
Method otherIndexedWriteMethod = other.getIndexedWriteMethod();
412
413
if (!compareMethods(getIndexedReadMethod(), otherIndexedReadMethod)) {
414
return false;
415
}
416
417
if (!compareMethods(getIndexedWriteMethod(), otherIndexedWriteMethod)) {
418
return false;
419
}
420
421
if (getIndexedPropertyType() != other.getIndexedPropertyType()) {
422
return false;
423
}
424
return super.equals(obj);
425
}
426
return false;
427
}
428
429
/**
430
* Package-private constructor.
431
* Merge two property descriptors. Where they conflict, give the
432
* second argument (y) priority over the first argument (x).
433
*
434
* @param x The first (lower priority) PropertyDescriptor
435
* @param y The second (higher priority) PropertyDescriptor
436
*/
437
438
IndexedPropertyDescriptor(PropertyDescriptor x, PropertyDescriptor y) {
439
super(x,y);
440
Method tr = null;
441
Method tw = null;
442
443
if (x instanceof IndexedPropertyDescriptor) {
444
IndexedPropertyDescriptor ix = (IndexedPropertyDescriptor) x;
445
tr = ix.getIndexedReadMethod();
446
tw = ix.getIndexedWriteMethod();
447
}
448
if (y instanceof IndexedPropertyDescriptor) {
449
IndexedPropertyDescriptor iy = (IndexedPropertyDescriptor) y;
450
Method yr = iy.getIndexedReadMethod();
451
if (isAssignable(tr, yr)) {
452
tr = yr;
453
}
454
455
Method yw = iy.getIndexedWriteMethod();
456
if (isAssignable(tw, yw)) {
457
tw = yw;
458
}
459
}
460
461
try {
462
if(tr != null) {
463
setIndexedReadMethod(tr);
464
}
465
if(tw != null) {
466
setIndexedWriteMethod(tw);
467
}
468
} catch(IntrospectionException ex) {
469
// Should not happen
470
throw new AssertionError(ex);
471
}
472
}
473
474
/*
475
* Package-private dup constructor
476
* This must isolate the new object from any changes to the old object.
477
*/
478
IndexedPropertyDescriptor(IndexedPropertyDescriptor old) {
479
super(old);
480
this.indexedReadMethodRef.set(old.indexedReadMethodRef.get());
481
this.indexedWriteMethodRef.set(old.indexedWriteMethodRef.get());
482
indexedPropertyTypeRef = old.indexedPropertyTypeRef;
483
indexedWriteMethodName = old.indexedWriteMethodName;
484
indexedReadMethodName = old.indexedReadMethodName;
485
}
486
487
void updateGenericsFor(Class<?> type) {
488
super.updateGenericsFor(type);
489
try {
490
setIndexedPropertyType(findIndexedPropertyType(this.indexedReadMethodRef.get(), this.indexedWriteMethodRef.get()));
491
}
492
catch (IntrospectionException exception) {
493
setIndexedPropertyType(null);
494
}
495
}
496
497
/**
498
* Returns a hash code value for the object.
499
* See {@link java.lang.Object#hashCode} for a complete description.
500
*
501
* @return a hash code value for this object.
502
* @since 1.5
503
*/
504
public int hashCode() {
505
int result = super.hashCode();
506
507
result = 37 * result + ((indexedWriteMethodName == null) ? 0 :
508
indexedWriteMethodName.hashCode());
509
result = 37 * result + ((indexedReadMethodName == null) ? 0 :
510
indexedReadMethodName.hashCode());
511
result = 37 * result + ((getIndexedPropertyType() == null) ? 0 :
512
getIndexedPropertyType().hashCode());
513
514
return result;
515
}
516
517
void appendTo(StringBuilder sb) {
518
super.appendTo(sb);
519
appendTo(sb, "indexedPropertyType", this.indexedPropertyTypeRef);
520
appendTo(sb, "indexedReadMethod", this.indexedReadMethodRef.get());
521
appendTo(sb, "indexedWriteMethod", this.indexedWriteMethodRef.get());
522
}
523
}
524
525