/* * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.beans; import java.lang.ref.Reference; import java.lang.reflect.Method; import java.util.Map.Entry; import com.sun.beans.introspect.PropertyInfo; /** * 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. *
* 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. * * @since 1.1 */ public class IndexedPropertyDescriptor extends PropertyDescriptor { private Reference extends Class>> indexedPropertyTypeRef; private final MethodRef indexedReadMethodRef = new MethodRef(); private final MethodRef indexedWriteMethodRef = new MethodRef(); 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. *
* 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,
Introspector.GET_PREFIX + NameGenerator.capitalize(propertyName),
Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName),
Introspector.GET_PREFIX + NameGenerator.capitalize(propertyName),
Introspector.SET_PREFIX + NameGenerator.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 property.
* @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));
}
/**
* Creates {@code IndexedPropertyDescriptor} from the specified property info.
*
* @param entry the key-value pair,
* where the {@code key} is the base name of the property (the rest of the method name)
* and the {@code value} is the automatically generated property info
* @param bound the flag indicating whether it is possible to treat this property as a bound property
*
* @since 9
*/
IndexedPropertyDescriptor(EntryPropertyDescriptor
against the specified object.
* Returns true if the objects are the same. Two PropertyDescriptor
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 argument (x).
*
* @param x The first (lower priority) PropertyDescriptor
* @param y The second (higher priority) PropertyDescriptor
*/
IndexedPropertyDescriptor(PropertyDescriptor x, PropertyDescriptor y) {
super(x,y);
Method tr = null;
Method tw = null;
if (x instanceof IndexedPropertyDescriptor) {
IndexedPropertyDescriptor ix = (IndexedPropertyDescriptor) x;
tr = ix.getIndexedReadMethod();
tw = ix.getIndexedWriteMethod();
}
if (y instanceof IndexedPropertyDescriptor) {
IndexedPropertyDescriptor iy = (IndexedPropertyDescriptor) y;
Method yr = iy.getIndexedReadMethod();
if (isAssignable(tr, yr)) {
tr = yr;
}
Method yw = iy.getIndexedWriteMethod();
if (isAssignable(tw, yw)) {
tw = yw;
}
}
try {
if(tr != null) {
setIndexedReadMethod(tr);
}
if(tw != null) {
setIndexedWriteMethod(tw);
}
} 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);
this.indexedReadMethodRef.set(old.indexedReadMethodRef.get());
this.indexedWriteMethodRef.set(old.indexedWriteMethodRef.get());
indexedPropertyTypeRef = old.indexedPropertyTypeRef;
indexedWriteMethodName = old.indexedWriteMethodName;
indexedReadMethodName = old.indexedReadMethodName;
}
void updateGenericsFor(Class> type) {
super.updateGenericsFor(type);
try {
setIndexedPropertyType(findIndexedPropertyType(this.indexedReadMethodRef.get(), this.indexedWriteMethodRef.get()));
}
catch (IntrospectionException exception) {
setIndexedPropertyType(null);
}
}
/**
* 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;
}
void appendTo(StringBuilder sb) {
super.appendTo(sb);
appendTo(sb, "indexedPropertyType", this.indexedPropertyTypeRef);
appendTo(sb, "indexedReadMethod", this.indexedReadMethodRef.get());
appendTo(sb, "indexedWriteMethod", this.indexedWriteMethodRef.get());
}
}