FileDocCategorySizeDatePackage
PropertyDescriptor.javaAPI DocJava SE 5 API20600Fri Aug 26 14:56:58 BST 2005java.beans

PropertyDescriptor

public class PropertyDescriptor extends FeatureDescriptor
A PropertyDescriptor describes one property that a Java Bean exports via a pair of accessor methods.

Fields Summary
private Reference
propertyTypeRef
private Reference
readMethodRef
private Reference
writeMethodRef
private Reference
propertyEditorClassRef
private boolean
bound
private boolean
constrained
private String
baseName
private String
writeMethodName
private String
readMethodName
Constructors Summary
public PropertyDescriptor(String propertyName, Class beanClass)
Constructs a PropertyDescriptor for a property that follows the standard Java convention by having getFoo and setFoo accessor methods. Thus if the argument name is "fred", it will assume that the writer method is "setFred" and the reader method is "getFred" (or "isFred" for a boolean property). Note that the property name should start with a lower case character, which will be capitalized in the method names.

param
propertyName The programmatic name of the property.
param
beanClass The Class object for the target bean. For example sun.beans.OurButton.class.
exception
IntrospectionException if an exception occurs during introspection.

	this(propertyName, beanClass, 
	     "is" + capitalize(propertyName), 
	     "set" + capitalize(propertyName));
    
public PropertyDescriptor(String propertyName, Class beanClass, String readMethodName, String writeMethodName)
This constructor takes the name of a simple property, and method names for reading and writing the property.

param
propertyName The programmatic name of the property.
param
beanClass The Class object for the target bean. For example sun.beans.OurButton.class.
param
readMethodName The name of the method used for reading the property value. May be null if the property is write-only.
param
writeMethodName The name of the method used for writing the property value. May be null if the property is read-only.
exception
IntrospectionException if an exception occurs during introspection.

	if (beanClass == null) {
	    throw new IntrospectionException("Target Bean class is null");
	}
	if (propertyName == null || propertyName.length() == 0) {
	    throw new IntrospectionException("bad property name");
	}
	if ("".equals(readMethodName) || "".equals(writeMethodName)) {
	    throw new IntrospectionException("read or write method name should not be the empty string");
	}	    
	setName(propertyName);
	setClass0(beanClass);

	this.readMethodName = readMethodName;
	if (readMethodName != null && getReadMethod() == null) {
	    throw new IntrospectionException("Method not found: " + readMethodName);
	}
	this.writeMethodName = writeMethodName;
	if (writeMethodName != null && getWriteMethod() == null) {
	    throw new IntrospectionException("Method not found: " + writeMethodName);
	}
	
    
PropertyDescriptor(PropertyDescriptor x, PropertyDescriptor y)
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

	super(x,y);

	if (y.baseName != null) {
	    baseName = y.baseName;
	} else {
	    baseName = x.baseName;
	}

	if (y.readMethodName != null) {
	    readMethodName = y.readMethodName;
	} else {
	    readMethodName = x.readMethodName;
	}

	if (y.writeMethodName != null) {
	    writeMethodName = y.writeMethodName;
	} else {
	    writeMethodName = x.writeMethodName;
	}

	if (y.propertyTypeRef != null) {
	    propertyTypeRef = y.propertyTypeRef;
	} else {
	    propertyTypeRef = x.propertyTypeRef;
	}

	// Figure out the merged read method.
	Method xr = x.getReadMethod();
	Method yr = y.getReadMethod();

	// Normally give priority to y's readMethod.
	try {
	    if (yr != null && yr.getDeclaringClass() == getClass0()) {
		setReadMethod(yr);
	    } else {
		setReadMethod(xr);
	    }
	} catch (IntrospectionException ex) {
	    // fall through
	}
	    
	// However, if both x and y reference read methods in the same class,
	// give priority to a boolean "is" method over a boolean "get" method.
	if (xr != null && yr != null &&
		   xr.getDeclaringClass() == yr.getDeclaringClass() &&
		   xr.getReturnType() == boolean.class &&
		   yr.getReturnType() == boolean.class &&
		   xr.getName().indexOf("is") == 0 &&
		   yr.getName().indexOf("get") == 0) {
	    try {
		setReadMethod(xr);
	    } catch (IntrospectionException ex) {
		// fall through
	    }
	}

	Method xw = x.getWriteMethod();
	Method yw = y.getWriteMethod();

	try {
	    if (yw != null && yw.getDeclaringClass() == getClass0()) {
		setWriteMethod(yw);
	    } else {
		setWriteMethod(xw);
	    }
	} catch (IntrospectionException ex) {
	    // Fall through
	}

	if (y.getPropertyEditorClass() != null) {
	    setPropertyEditorClass(y.getPropertyEditorClass());
	} else {
	    setPropertyEditorClass(x.getPropertyEditorClass());
	}
	

	bound = x.bound | y.bound;
	constrained = x.constrained | y.constrained;
    
PropertyDescriptor(PropertyDescriptor old)

	super(old);
	propertyTypeRef = old.propertyTypeRef;
	readMethodRef = old.readMethodRef;
	writeMethodRef = old.writeMethodRef;
	propertyEditorClassRef = old.propertyEditorClassRef;

	writeMethodName = old.writeMethodName;
	readMethodName = old.readMethodName;
	baseName = old.baseName;

	bound = old.bound;
	constrained = old.constrained;
    
public PropertyDescriptor(String propertyName, Method readMethod, Method writeMethod)
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 value. May be null if the property is write-only.
param
writeMethod The method used for writing the property value. May be null if the property is read-only.
exception
IntrospectionException if an exception occurs during introspection.

	if (propertyName == null || propertyName.length() == 0) {
	    throw new IntrospectionException("bad property name");
	}
	setName(propertyName);
	setReadMethod(readMethod);
	setWriteMethod(writeMethod);
    
Methods Summary
booleancompareMethods(java.lang.reflect.Method a, java.lang.reflect.Method b)
Package private helper method for Descriptor .equals methods.

param
a first method to compare
param
b second method to compare
return
boolean to indicate that the methods are equivalent

	// Note: perhaps this should be a protected method in FeatureDescriptor
	if ((a == null) != (b == null)) {
	    return false;
	}

	if (a != null && b != null) {
	    if (!a.equals(b)) {
		return false;
	    }
	}
	return true;
    
public java.beans.PropertyEditorcreatePropertyEditor(java.lang.Object bean)
Constructs an instance of a property editor using the current property editor class.

If the property editor class has a public constructor that takes an Object argument then it will be invoked using the bean parameter as the argument. Otherwise, the default constructor will be invoked.

param
bean the source object
return
a property editor instance or null if a property editor has not been defined or cannot be created
since
1.5

	Object editor = null;

	Class cls = getPropertyEditorClass();
	if (cls != null) {
	    Constructor ctor = null;
	    if (bean != null) {
		try {
		    ctor = cls.getConstructor(new Class[] { Object.class });
		} catch (Exception ex) {
		    // Fall through
		}
	    }
	    try {
		if (ctor == null) {
		    editor = cls.newInstance();
		} else {
		    editor = ctor.newInstance(new Object[] { bean });
		}
	    } catch (Exception ex) {
		// A serious error has occured. 
		// Proably due to an invalid property editor.
		throw new RuntimeException("PropertyEditor not instantiated", 
					   ex);
	    }
	}
	return (PropertyEditor)editor;
    
public booleanequals(java.lang.Object obj)
Compares this PropertyDescriptor against the specified object. Returns true if the objects are the same. Two PropertyDescriptors are the same if the read, write, property types, property editor and flags are equivalent.

since
1.4

	if (this == obj) {
	    return true;
	}
	if (obj != null && obj instanceof PropertyDescriptor) {
	    PropertyDescriptor other = (PropertyDescriptor)obj;
	    Method otherReadMethod = other.getReadMethod();
	    Method otherWriteMethod = other.getWriteMethod();

	    if (!compareMethods(getReadMethod(), otherReadMethod)) {
		return false;
	    }

	    if (!compareMethods(getWriteMethod(), otherWriteMethod)) {
		return false;
	    }

	    if (getPropertyType() == other.getPropertyType() && 
		getPropertyEditorClass() == other.getPropertyEditorClass() &&
		bound == other.isBound() && constrained == other.isConstrained() &&
		writeMethodName == other.writeMethodName && 
		readMethodName == other.readMethodName) {
		return true;
	    }
	}
	return false;
    
private java.lang.ClassfindPropertyType(java.lang.reflect.Method readMethod, java.lang.reflect.Method writeMethod)
Returns the property type that corresponds to the read and write method. The type precedence is given to the readMethod.

return
the type of the property descriptor or null if both read and write methods are null.
throws
IntrospectionException if the read or write method is invalid

	Class propertyType = null;
	try {
	    if (readMethod != null) {
		Class[] params = readMethod.getParameterTypes();
		if (params.length != 0) {
		    throw new IntrospectionException("bad read method arg count: " 
						     + readMethod);
		}
		propertyType = readMethod.getReturnType();
		if (propertyType == Void.TYPE) {
		    throw new IntrospectionException("read method " +
					readMethod.getName() + " returns void");
		}
	    }
	    if (writeMethod != null) {
		Class params[] = writeMethod.getParameterTypes();
		if (params.length != 1) {
		    throw new IntrospectionException("bad write method arg count: "
						     + writeMethod);
		}
		if (propertyType != null && propertyType != params[0]) {
		    throw new IntrospectionException("type mismatch between read and write methods");
		}
		propertyType = params[0];
	    }
	} catch (IntrospectionException ex) {
	    throw ex;
	}
	return propertyType;
    
java.lang.StringgetBaseName()

	if (baseName == null) {
	    baseName = capitalize(getName());
	}
	return baseName;
    
public java.lang.ClassgetPropertyEditorClass()
Gets any explicit PropertyEditor Class that has been registered for this property.

return
Any explicit PropertyEditor Class that has been registered for this property. Normally this will return "null", indicating that no special editor has been registered, so the PropertyEditorManager should be used to locate a suitable PropertyEditor.

	return (Class)getObject(propertyEditorClassRef);
    
public synchronized java.lang.ClassgetPropertyType()
Gets the Class object for the property.

return
The Java type info for the property. Note that the "Class" object may describe a built-in Java type such as "int". The result may be "null" if this is an indexed property that does not support non-indexed access.

This is the type that will be returned by the ReadMethod.

	Class type = getPropertyType0();
	if (type  == null) {
	    try {
		type = findPropertyType(getReadMethod(), getWriteMethod());
		setPropertyType(type);
	    } catch (IntrospectionException ex) {
		// Fall 
	    }
	}
	return type;
    
private java.lang.ClassgetPropertyType0()

	return (Class)getObject(propertyTypeRef);
    
public synchronized java.lang.reflect.MethodgetReadMethod()
Gets the method that should be used to read the property value.

return
The method that should be used to read the property value. May return null if the property can't be read.

	Method readMethod = getReadMethod0();
	if (readMethod == null) {
	    Class cls = getClass0();
	    if (cls == null || (readMethodName == null && readMethodRef == null)) {
		// The read method was explicitly set to null.
		return null;
	    }
	    if (readMethodName == null) {
		Class type = getPropertyType0();
		if (type == boolean.class || type == null) {
		    readMethodName = "is" + getBaseName();
		} else {
		    readMethodName = "get" + getBaseName();
		}
	    }
	    
	    // Since there can be multiple write methods but only one getter
	    // method, find the getter method first so that you know what the
	    // property type is.  For booleans, there can be "is" and "get"
	    // methods.  If an "is" method exists, this is the official
	    // reader method so look for this one first.
	    readMethod = Introspector.findMethod(cls, readMethodName, 0);
	    if (readMethod == null) {
		readMethodName = "get" + getBaseName();
		readMethod = Introspector.findMethod(cls, readMethodName, 0);
	    }
	    try {
		setReadMethod(readMethod);
	    } catch (IntrospectionException ex) {
		// fall
	    }
	}
	return readMethod;
    
private java.lang.reflect.MethodgetReadMethod0()

	return (Method)getObject(readMethodRef);
    
public synchronized java.lang.reflect.MethodgetWriteMethod()
Gets the method that should be used to write the property value.

return
The method that should be used to write the property value. May return null if the property can't be written.

	Method writeMethod = getWriteMethod0();
	if (writeMethod == null) {
	    Class cls = getClass0();
	    if (cls == null || (writeMethodName == null && writeMethodRef == null)) {
		// The write method was explicitly set to null.
		return null;
	    }

	    // We need the type to fetch the correct method.
	    Class type = getPropertyType0();
	    if (type == null) {
		try {
		    // Can't use getPropertyType since it will lead to recursive loop.
		    type = findPropertyType(getReadMethod(), null);
		    setPropertyType(type);
		} catch (IntrospectionException ex) {
		    // Without the correct property type we can't be guaranteed 
		    // to find the correct method.
		    return null;
		}
	    }
		    
	    if (writeMethodName == null) {
		writeMethodName = "set" + getBaseName();
	    }

	    writeMethod = Introspector.findMethod(cls, writeMethodName, 1, 
   			  (type == null) ? null : new Class[] { type });
	    try {
		setWriteMethod(writeMethod);
	    } catch (IntrospectionException ex) {
		// fall through
	    }
	}
	return writeMethod;
    
private java.lang.reflect.MethodgetWriteMethod0()

	return (Method)getObject(writeMethodRef);
    
public inthashCode()
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

	int result = 7;

	result = 37 * result + ((getPropertyType() == null) ? 0 : 
				getPropertyType().hashCode());
	result = 37 * result + ((getReadMethod() == null) ? 0 : 
				getReadMethod().hashCode());
	result = 37 * result + ((getWriteMethod() == null) ? 0 : 
				getWriteMethod().hashCode());
	result = 37 * result + ((getPropertyEditorClass() == null) ? 0 : 
				getPropertyEditorClass().hashCode());
	result = 37 * result + ((writeMethodName == null) ? 0 : 
				writeMethodName.hashCode());
	result = 37 * result + ((readMethodName == null) ? 0 : 
				readMethodName.hashCode());
	result = 37 * result + getName().hashCode();
	result = 37 * result + ((bound == false) ? 0 : 1);
	result = 37 * result + ((constrained == false) ? 0 : 1);

	return result;
    
public booleanisBound()
Updates to "bound" properties will cause a "PropertyChange" event to get fired when the property is changed.

return
True if this is a bound property.

	return bound;
    
public booleanisConstrained()
Attempted updates to "Constrained" properties will cause a "VetoableChange" event to get fired when the property is changed.

return
True if this is a constrained property.

	return constrained;
    
public voidsetBound(boolean bound)
Updates to "bound" properties will cause a "PropertyChange" event to get fired when the property is changed.

param
bound True if this is a bound property.

	this.bound = bound;
    
voidsetClass0(java.lang.Class clz)
Overridden to ensure that a super class doesn't take precedent

	if (getClass0() != null && clz.isAssignableFrom(getClass0())) {
	    // dont replace a subclass with a superclass
	    return;
	}
	super.setClass0(clz);
    
public voidsetConstrained(boolean constrained)
Attempted updates to "Constrained" properties will cause a "VetoableChange" event to get fired when the property is changed.

param
constrained True if this is a constrained property.

	this.constrained = constrained;
    
public voidsetPropertyEditorClass(java.lang.Class propertyEditorClass)
Normally PropertyEditors will be found using the PropertyEditorManager. However if for some reason you want to associate a particular PropertyEditor with a given property, then you can do it with this method.

param
propertyEditorClass The Class for the desired PropertyEditor.

	propertyEditorClassRef = createReference(propertyEditorClass);
    
private voidsetPropertyType(java.lang.Class type)

	propertyTypeRef = createReference(type);
    
public synchronized voidsetReadMethod(java.lang.reflect.Method readMethod)
Sets the method that should be used to read the property value.

param
readMethod The new read method.

	if (readMethod == null) {
	    readMethodName = null;
	    readMethodRef = null;
	    return;
	}
	// The property type is determined by the read method.
	setPropertyType(findPropertyType(readMethod, getWriteMethod0()));
	setClass0(readMethod.getDeclaringClass());

	readMethodName = readMethod.getName();
	readMethodRef = createReference(readMethod, true);
    
public synchronized voidsetWriteMethod(java.lang.reflect.Method writeMethod)
Sets the method that should be used to write the property value.

param
writeMethod The new write method.

	if (writeMethod == null) {
	    writeMethodName = null;
	    writeMethodRef = null;
	    return;
	}
	// Set the property type - which validates the method
	setPropertyType(findPropertyType(getReadMethod(), writeMethod));
	setClass0(writeMethod.getDeclaringClass());

	writeMethodName = writeMethod.getName();
	writeMethodRef = createReference(writeMethod, true);