/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is NetBeans. The Initial Developer of the Original
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
* Microsystems, Inc. All Rights Reserved.
*/
package org.openide.explorer.propertysheet;
import java.beans.*;
import java.lang.reflect.*;
import org.openide.ErrorManager;
/** The default implementation of PropertyModel interface.
* It takes the bean instance and the property name which should
* be accessed through PropertyModel methods. We now implement
* the new ExPropertyModel interface (which extends PropertyModel).
*
* @deprecated Use org.openide.nodes.PropertySupport.Reflection instead
* @author Jaroslav Tulach, Petr Hamernik
*/
public class DefaultPropertyModel extends Object implements ExPropertyModel, PropertyChangeListener {
/** The Java Bean */
Object bean;
/** Name of the property of the bean. */
String propertyName; //package private so error handling code can pick up
//the property name if the user enters an invalid value
/** support for the properties changes. */
private PropertyChangeSupport support;
/** Property descriptor for the bean. */
private PropertyDescriptor prop;
/** Read method if exists one. */
private Method readMethod;
/** Write method if exists one. */
private Method writeMethod;
/** Type of the property. */
private Class propertyTypeClass;
/** When we call setValue we want to disable refiring of property change*/
private boolean donotfire = false;
/** Creates new DefaultPropertyModel.
* @param bean the java bean to be introspected
* @param propertyName name of the property
*
* @exception IllegalArgumentException if there is any problem
* with the parameters (introspection of bean,...)
*/
public DefaultPropertyModel(Object bean, String propertyName) throws IllegalArgumentException {
this (bean, findInfo (bean, propertyName));
}
/** Creates new DefaultPropertyModel with provided specific
* PropertyDescriptor. This can be useful if one needs to
* set to provide specific attributes to the property editor.
*
* PropertyDescriptor pd = new PropertyDescriptor ("myProperty", bean.getClass ());
* pd.setPropertyEditorClass (PropertyEditorManager.findEditor (Object.class));
*
* // special attributes to the property editor
* pb.setValue ("superClass", MyProperty.class);
*
*
* model = new DefaultPropertyModel (bean, pd);
* panel = new PropertyPanel (model);
*
* This constructor replaces the default use of BeanInfo and that is why
* simplifies the use of ExPropertyEditors.
*
* @param bean the java bean to be introspected
* @param descr the property descriptor of the property to use
*
* @since 2.4
*/
public DefaultPropertyModel(Object bean, PropertyDescriptor descr) {
this.bean = bean;
this.propertyName = descr.getName ();
support = new PropertyChangeSupport(this);
this.prop = descr;
this.propertyTypeClass = descr.getPropertyType();
this.readMethod = descr.getReadMethod ();
this.writeMethod = descr.getWriteMethod ();
try {
try {
// bugfix #16703 addPropertyChangeListener(String, PropertyChangeListener) is looked first
// is not then addPropertyChangeListener(PropertyChangeListener) is looked
Method addList = bean.getClass().getMethod("addPropertyChangeListener", new Class[] { String.class, PropertyChangeListener.class }); // NOI18N
addList.invoke(bean, new Object[] {
propertyName,
org.openide.util.WeakListeners.propertyChange(this, bean)
});
} catch (NoSuchMethodException nsme) {
try {
Method addList = bean.getClass().getMethod("addPropertyChangeListener", new Class[] {PropertyChangeListener.class }); // NOI18N
addList.invoke(bean, new Object[] {
org.openide.util.WeakListeners.propertyChange(this, bean)
});
} catch (NoSuchMethodException nosme) {
// be quiet
}
}
} catch (Exception e) {
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
}
}
/** Finds property descriptor for a bean.
* @param bean the bean
* @param name name of the property to find
* @return the descriptor
* @exception IllegalArgumentException if the method is not found
*/
private static PropertyDescriptor findInfo (Object bean, String name)
throws IllegalArgumentException {
try {
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
PropertyDescriptor[] descr = beanInfo.getPropertyDescriptors();
for (int i = 0; i < descr.length; i++) {
if (descr[i].getName().equals(name)) {
return descr[i];
}
}
throw new IllegalArgumentException (
"No property named " + name + " in class " + bean.getClass () // NOI18N
);
} catch (IntrospectionException e) {
IllegalArgumentException newEx = new IllegalArgumentException();
ErrorManager.getDefault().annotate (newEx, e);
throw newEx;
}
}
/**
* @return the class of the property.
*/
public Class getPropertyType() {
return propertyTypeClass;
}
/** Getter for current value of a property.
*/
public Object getValue() throws InvocationTargetException {
try {
return (readMethod == null) ?
null :
readMethod.invoke(bean, new Object[] {});
}
catch (IllegalAccessException e) {
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
throw new InvocationTargetException(e);
}
}
/** Setter for a value of a property.
* @param v the value
* @exception InvocationTargetException
*/
public void setValue(Object v) throws InvocationTargetException {
try {
if (writeMethod != null) {
donotfire = true;
writeMethod.invoke(bean, new Object[] {v});
donotfire = false;
}
}
catch (IllegalAccessException e) {
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
throw new InvocationTargetException(e);
}
}
/** Adds listener to change of the value.
*/
public void addPropertyChangeListener(PropertyChangeListener l) {
support.addPropertyChangeListener(l);
}
/** Removes listener to change of the value.
*/
public void removePropertyChangeListener(PropertyChangeListener l) {
support.removePropertyChangeListener(l);
}
/** Implementation of PropertyChangeListener method */
public void propertyChange(PropertyChangeEvent evt) {
if (propertyName.equals(evt.getPropertyName()) && (!donotfire)) {
support.firePropertyChange(PROP_VALUE, evt.getOldValue(), evt.getNewValue());
}
}
/** The class of the property editor or null
* if default property editor should be used.
*/
public Class getPropertyEditorClass() {
return prop.getPropertyEditorClass();
}
/**
* Returns an array of beans/nodes that this property belongs
* to. Implements the method from ExPropertyModel interface.
*/
public Object[] getBeans() {
return new Object[] { bean };
}
/**
* Returns descriptor describing the property.
* Implements the method from ExPropertyModel interface.
*/
public FeatureDescriptor getFeatureDescriptor() {
return prop;
}
}