Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/java/beans/IndexedPropertyDescriptor.java
41152 views
1
/*
2
* Copyright (c) 1996, 2014, 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
package java.beans;
26
27
import java.lang.ref.Reference;
28
import java.lang.reflect.Method;
29
import java.util.Map.Entry;
30
31
import com.sun.beans.introspect.PropertyInfo;
32
33
/**
34
* An IndexedPropertyDescriptor describes a property that acts like an
35
* array and has an indexed read and/or indexed write method to access
36
* specific elements of the array.
37
* <p>
38
* An indexed property may also provide simple non-indexed read and write
39
* methods. If these are present, they read and write arrays of the type
40
* returned by the indexed read method.
41
*
42
* @since 1.1
43
*/
44
45
public class IndexedPropertyDescriptor extends PropertyDescriptor {
46
47
private Reference<? extends Class<?>> indexedPropertyTypeRef;
48
private final MethodRef indexedReadMethodRef = new MethodRef();
49
private final MethodRef indexedWriteMethodRef = new MethodRef();
50
51
private String indexedReadMethodName;
52
private String indexedWriteMethodName;
53
54
/**
55
* This constructor constructs an IndexedPropertyDescriptor for a property
56
* that follows the standard Java conventions by having getFoo and setFoo
57
* accessor methods, for both indexed access and array access.
58
* <p>
59
* Thus if the argument name is "fred", it will assume that there
60
* is an indexed reader method "getFred", a non-indexed (array) reader
61
* method also called "getFred", an indexed writer method "setFred",
62
* and finally a non-indexed writer method "setFred".
63
*
64
* @param propertyName The programmatic name of the property.
65
* @param beanClass The Class object for the target bean.
66
* @exception IntrospectionException if an exception occurs during
67
* introspection.
68
*/
69
public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass)
70
throws IntrospectionException {
71
this(propertyName, beanClass,
72
Introspector.GET_PREFIX + NameGenerator.capitalize(propertyName),
73
Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName),
74
Introspector.GET_PREFIX + NameGenerator.capitalize(propertyName),
75
Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName));
76
}
77
78
/**
79
* This constructor takes the name of a simple property, and method
80
* names for reading and writing the property, both indexed
81
* and non-indexed.
82
*
83
* @param propertyName The programmatic name of the property.
84
* @param beanClass The Class object for the target bean.
85
* @param readMethodName The name of the method used for reading the property
86
* values as an array. May be null if the property is write-only
87
* or must be indexed.
88
* @param writeMethodName The name of the method used for writing the property
89
* values as an array. May be null if the property is read-only
90
* or must be indexed.
91
* @param indexedReadMethodName The name of the method used for reading
92
* an indexed property value.
93
* May be null if the property is write-only.
94
* @param indexedWriteMethodName The name of the method used for writing
95
* an indexed property value.
96
* May be null if the property is read-only.
97
* @exception IntrospectionException if an exception occurs during
98
* introspection.
99
*/
100
public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass,
101
String readMethodName, String writeMethodName,
102
String indexedReadMethodName, String indexedWriteMethodName)
103
throws IntrospectionException {
104
super(propertyName, beanClass, readMethodName, writeMethodName);
105
106
this.indexedReadMethodName = indexedReadMethodName;
107
if (indexedReadMethodName != null && getIndexedReadMethod() == null) {
108
throw new IntrospectionException("Method not found: " + indexedReadMethodName);
109
}
110
111
this.indexedWriteMethodName = indexedWriteMethodName;
112
if (indexedWriteMethodName != null && getIndexedWriteMethod() == null) {
113
throw new IntrospectionException("Method not found: " + indexedWriteMethodName);
114
}
115
// Implemented only for type checking.
116
findIndexedPropertyType(getIndexedReadMethod(), getIndexedWriteMethod());
117
}
118
119
/**
120
* This constructor takes the name of a simple property, and Method
121
* objects for reading and writing the property.
122
*
123
* @param propertyName The programmatic name of the property.
124
* @param readMethod The method used for reading the property values as an array.
125
* May be null if the property is write-only or must be indexed.
126
* @param writeMethod The method used for writing the property values as an array.
127
* May be null if the property is read-only or must be indexed.
128
* @param indexedReadMethod The method used for reading an indexed property value.
129
* May be null if the property is write-only.
130
* @param indexedWriteMethod The method used for writing an indexed property value.
131
* May be null if the property is read-only.
132
* @exception IntrospectionException if an exception occurs during
133
* introspection.
134
*/
135
public IndexedPropertyDescriptor(String propertyName, Method readMethod, Method writeMethod,
136
Method indexedReadMethod, Method indexedWriteMethod)
137
throws IntrospectionException {
138
super(propertyName, readMethod, writeMethod);
139
140
setIndexedReadMethod0(indexedReadMethod);
141
setIndexedWriteMethod0(indexedWriteMethod);
142
143
// Type checking
144
setIndexedPropertyType(findIndexedPropertyType(indexedReadMethod, indexedWriteMethod));
145
}
146
147
/**
148
* Creates {@code IndexedPropertyDescriptor} from the specified property info.
149
*
150
* @param entry the key-value pair,
151
* where the {@code key} is the base name of the property (the rest of the method name)
152
* and the {@code value} is the automatically generated property info
153
* @param bound the flag indicating whether it is possible to treat this property as a bound property
154
*
155
* @since 9
156
*/
157
IndexedPropertyDescriptor(Entry<String,PropertyInfo> entry, boolean bound) {
158
super(entry, bound);
159
PropertyInfo info = entry.getValue().getIndexed();
160
setIndexedReadMethod0(info.getReadMethod());
161
setIndexedWriteMethod0(info.getWriteMethod());
162
setIndexedPropertyType(info.getPropertyType());
163
}
164
165
/**
166
* Gets the method that should be used to read an indexed
167
* property value.
168
*
169
* @return The method that should be used to read an indexed
170
* property value.
171
* May return null if the property isn't indexed or is write-only.
172
*/
173
public synchronized Method getIndexedReadMethod() {
174
Method indexedReadMethod = this.indexedReadMethodRef.get();
175
if (indexedReadMethod == null) {
176
Class<?> cls = getClass0();
177
if (cls == null ||
178
(indexedReadMethodName == null && !this.indexedReadMethodRef.isSet())) {
179
// the Indexed readMethod was explicitly set to null.
180
return null;
181
}
182
String nextMethodName = Introspector.GET_PREFIX + getBaseName();
183
if (indexedReadMethodName == null) {
184
Class<?> type = getIndexedPropertyType0();
185
if (type == boolean.class || type == null) {
186
indexedReadMethodName = Introspector.IS_PREFIX + getBaseName();
187
} else {
188
indexedReadMethodName = nextMethodName;
189
}
190
}
191
192
Class<?>[] args = { int.class };
193
indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 1, args);
194
if ((indexedReadMethod == null) && !indexedReadMethodName.equals(nextMethodName)) {
195
// no "is" method, so look for a "get" method.
196
indexedReadMethodName = nextMethodName;
197
indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 1, args);
198
}
199
setIndexedReadMethod0(indexedReadMethod);
200
}
201
return indexedReadMethod;
202
}
203
204
/**
205
* Sets the method that should be used to read an indexed property value.
206
*
207
* @param readMethod The new indexed read method.
208
* @throws IntrospectionException if an exception occurs during
209
* introspection.
210
*
211
* @since 1.2
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
* @since 1.2
293
*/
294
public synchronized void setIndexedWriteMethod(Method writeMethod)
295
throws IntrospectionException {
296
297
// If the indexed property type has not been set, then set it.
298
Class<?> type = findIndexedPropertyType(getIndexedReadMethod(),
299
writeMethod);
300
setIndexedPropertyType(type);
301
setIndexedWriteMethod0(writeMethod);
302
}
303
304
private void setIndexedWriteMethod0(Method writeMethod) {
305
this.indexedWriteMethodRef.set(writeMethod);
306
if (writeMethod == null) {
307
indexedWriteMethodName = null;
308
return;
309
}
310
setClass0(writeMethod.getDeclaringClass());
311
312
indexedWriteMethodName = writeMethod.getName();
313
setTransient(writeMethod.getAnnotation(Transient.class));
314
}
315
316
/**
317
* Returns the Java type info for the indexed property.
318
* Note that the {@code Class} object may describe
319
* primitive Java types such as {@code int}.
320
* This type is returned by the indexed read method
321
* or is used as the parameter type of the indexed write method.
322
*
323
* @return the {@code Class} object that represents the Java type info,
324
* or {@code null} if the type cannot be determined
325
*/
326
public synchronized Class<?> getIndexedPropertyType() {
327
Class<?> type = getIndexedPropertyType0();
328
if (type == null) {
329
try {
330
type = findIndexedPropertyType(getIndexedReadMethod(),
331
getIndexedWriteMethod());
332
setIndexedPropertyType(type);
333
} catch (IntrospectionException ex) {
334
// fall
335
}
336
}
337
return type;
338
}
339
340
// Private methods which set get/set the Reference objects
341
342
private void setIndexedPropertyType(Class<?> type) {
343
this.indexedPropertyTypeRef = getWeakReference(type);
344
}
345
346
private Class<?> getIndexedPropertyType0() {
347
return (this.indexedPropertyTypeRef != null)
348
? this.indexedPropertyTypeRef.get()
349
: null;
350
}
351
352
private Class<?> findIndexedPropertyType(Method indexedReadMethod,
353
Method indexedWriteMethod)
354
throws IntrospectionException {
355
Class<?> indexedPropertyType = null;
356
357
if (indexedReadMethod != null) {
358
Class<?>[] params = getParameterTypes(getClass0(), indexedReadMethod);
359
if (params.length != 1) {
360
throw new IntrospectionException("bad indexed read method arg count");
361
}
362
if (params[0] != Integer.TYPE) {
363
throw new IntrospectionException("non int index to indexed read method");
364
}
365
indexedPropertyType = getReturnType(getClass0(), indexedReadMethod);
366
if (indexedPropertyType == Void.TYPE) {
367
throw new IntrospectionException("indexed read method returns void");
368
}
369
}
370
if (indexedWriteMethod != null) {
371
Class<?>[] params = getParameterTypes(getClass0(), indexedWriteMethod);
372
if (params.length != 2) {
373
throw new IntrospectionException("bad indexed write method arg count");
374
}
375
if (params[0] != Integer.TYPE) {
376
throw new IntrospectionException("non int index to indexed write method");
377
}
378
if (indexedPropertyType == null || params[1].isAssignableFrom(indexedPropertyType)) {
379
indexedPropertyType = params[1];
380
} else if (!indexedPropertyType.isAssignableFrom(params[1])) {
381
throw new IntrospectionException(
382
"type mismatch between indexed read and indexed write methods: "
383
+ getName());
384
}
385
}
386
Class<?> propertyType = getPropertyType();
387
if (propertyType != null && (!propertyType.isArray() ||
388
propertyType.getComponentType() != indexedPropertyType)) {
389
throw new IntrospectionException("type mismatch between indexed and non-indexed methods: "
390
+ getName());
391
}
392
return indexedPropertyType;
393
}
394
395
/**
396
* Compares this {@code PropertyDescriptor} against the specified object.
397
* Returns true if the objects are the same. Two {@code PropertyDescriptor}s
398
* are the same if the read, write, property types, property editor and
399
* flags are equivalent.
400
*
401
* @since 1.4
402
*/
403
public boolean equals(Object obj) {
404
// Note: This would be identical to PropertyDescriptor but they don't
405
// share the same fields.
406
if (this == obj) {
407
return true;
408
}
409
410
if (obj != null && obj instanceof IndexedPropertyDescriptor) {
411
IndexedPropertyDescriptor other = (IndexedPropertyDescriptor)obj;
412
Method otherIndexedReadMethod = other.getIndexedReadMethod();
413
Method otherIndexedWriteMethod = other.getIndexedWriteMethod();
414
415
if (!compareMethods(getIndexedReadMethod(), otherIndexedReadMethod)) {
416
return false;
417
}
418
419
if (!compareMethods(getIndexedWriteMethod(), otherIndexedWriteMethod)) {
420
return false;
421
}
422
423
if (getIndexedPropertyType() != other.getIndexedPropertyType()) {
424
return false;
425
}
426
return super.equals(obj);
427
}
428
return false;
429
}
430
431
/**
432
* Package-private constructor.
433
* Merge two property descriptors. Where they conflict, give the
434
* second argument (y) priority over the first argument (x).
435
*
436
* @param x The first (lower priority) PropertyDescriptor
437
* @param y The second (higher priority) PropertyDescriptor
438
*/
439
440
IndexedPropertyDescriptor(PropertyDescriptor x, PropertyDescriptor y) {
441
super(x,y);
442
Method tr = null;
443
Method tw = null;
444
445
if (x instanceof IndexedPropertyDescriptor) {
446
IndexedPropertyDescriptor ix = (IndexedPropertyDescriptor) x;
447
tr = ix.getIndexedReadMethod();
448
tw = ix.getIndexedWriteMethod();
449
}
450
if (y instanceof IndexedPropertyDescriptor) {
451
IndexedPropertyDescriptor iy = (IndexedPropertyDescriptor) y;
452
Method yr = iy.getIndexedReadMethod();
453
if (isAssignable(tr, yr)) {
454
tr = yr;
455
}
456
457
Method yw = iy.getIndexedWriteMethod();
458
if (isAssignable(tw, yw)) {
459
tw = yw;
460
}
461
}
462
463
try {
464
if(tr != null) {
465
setIndexedReadMethod(tr);
466
}
467
if(tw != null) {
468
setIndexedWriteMethod(tw);
469
}
470
} catch(IntrospectionException ex) {
471
// Should not happen
472
throw new AssertionError(ex);
473
}
474
}
475
476
/*
477
* Package-private dup constructor
478
* This must isolate the new object from any changes to the old object.
479
*/
480
IndexedPropertyDescriptor(IndexedPropertyDescriptor old) {
481
super(old);
482
this.indexedReadMethodRef.set(old.indexedReadMethodRef.get());
483
this.indexedWriteMethodRef.set(old.indexedWriteMethodRef.get());
484
indexedPropertyTypeRef = old.indexedPropertyTypeRef;
485
indexedWriteMethodName = old.indexedWriteMethodName;
486
indexedReadMethodName = old.indexedReadMethodName;
487
}
488
489
void updateGenericsFor(Class<?> type) {
490
super.updateGenericsFor(type);
491
try {
492
setIndexedPropertyType(findIndexedPropertyType(this.indexedReadMethodRef.get(), this.indexedWriteMethodRef.get()));
493
}
494
catch (IntrospectionException exception) {
495
setIndexedPropertyType(null);
496
}
497
}
498
499
/**
500
* Returns a hash code value for the object.
501
* See {@link java.lang.Object#hashCode} for a complete description.
502
*
503
* @return a hash code value for this object.
504
* @since 1.5
505
*/
506
public int hashCode() {
507
int result = super.hashCode();
508
509
result = 37 * result + ((indexedWriteMethodName == null) ? 0 :
510
indexedWriteMethodName.hashCode());
511
result = 37 * result + ((indexedReadMethodName == null) ? 0 :
512
indexedReadMethodName.hashCode());
513
result = 37 * result + ((getIndexedPropertyType() == null) ? 0 :
514
getIndexedPropertyType().hashCode());
515
516
return result;
517
}
518
519
void appendTo(StringBuilder sb) {
520
super.appendTo(sb);
521
appendTo(sb, "indexedPropertyType", this.indexedPropertyTypeRef);
522
appendTo(sb, "indexedReadMethod", this.indexedReadMethodRef.get());
523
appendTo(sb, "indexedWriteMethod", this.indexedWriteMethodRef.get());
524
}
525
}
526
527