package cern.gp.explorer;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import org.openide.explorer.view.NodeTableModel;
import org.openide.nodes.Node;
import org.openide.nodes.Node.Property;
import org.openide.nodes.Node.PropertySet;
import cern.gp.nodes.GPNode;
import cern.gp.nodes.NodeFactory;
import cern.gp.util.ArrayUtil;
import java.util.ArrayList;
/**
* A class that contains common code related to the Tables contained in the
* ListTableExplorer and TreeTableExplorer.
* Both ListTableExplorer and TreeTableExplorer contain an instance of this class
* and delegate to it.
*
* @version $Revision: 1.2 $ $Date: 2006/09/25 08:52:36 $
* @author Vito Baggiolini
*/
class TableHolderImpl implements TableHolder {
private TablePropertyHolder tablePropertyHolder;
TableHolderImpl(TablePropertyHolder tablePropertyHolder) {
this.tablePropertyHolder = tablePropertyHolder;
}
/**
* @deprecated
*/
public void setTableColumns(Class beanClass) throws IntrospectionException {
setTableColumns(calcPropertyDescriptorsFor(beanClass, null));
}
/**
* @deprecated
*/
public void setTableColumns(Class beanClass, String[] propNames) throws IntrospectionException {
setTableColumns(TableHolderImpl.calcPropertyDescriptorsFor(beanClass, propNames));
}
/* (non-Javadoc)
* @see cern.gp.explorer.TableHolder#setTableColumns(java.lang.Class[], java.lang.String[])
*/
public void setTableColumns(Class[] propTypes, String[] propNames) {
setTableColumns(propTypes, propNames, null);
}
/* non-javadoc
* Sets the colums of the Table. The colums are identified by their name and their type.
* Please make sure that the two arrays passed as arguments correspond.
* <Strong>Caution</strong>do not use this with beans that implement the
* {@link cern.gp.beans.BeanSupport#getPropertyInfo} method to customize settings for
* properties. For such beans use {{#setTableColumns(Object, String[])} instead.
*
* @param propNames the names of the properties to be displayed
* @param propTypes the types of the properties corresponding to the names
*/
public void setTableColumns(Class[] propTypes, String[] propNames, boolean[] sortable) {
//if (NewAssert.assertTrue(propTypes.length == propNames.length, "not the same length for the two arrays") == false) { return; }
Property[] propArr = new Property[propTypes.length];
for (int ix = 0; ix < propArr.length; ix++) {
propArr[ix] = new TableViewColumnProperty(propNames[ix], null, propTypes[ix]);
}
tablePropertyHolder.setProperties(propArr, sortable);
}
public void setTableColumns(Object bean) throws IntrospectionException {
setTableColumns(bean, null);
}
public void setTableColumns(Object bean, String[] propNames) throws IntrospectionException {
setTableColumns(bean, propNames, null);
}
public void setTableColumns(Object bean, String[] propNames, boolean[] sortable) throws IntrospectionException {
// TODO check if there is a more efficient way to do this!
setTableColumns(NodeFactory.createNode(bean), propNames, sortable);
}
/* (non-Javadoc)
* @see cern.gp.explorer.TableHolder#setTableColumns(cern.gp.nodes.GPNode, java.lang.String[])
*/
public void setTableColumns(GPNode node, String[] propNames) {
setTableColumns(node, propNames, null);
}
public void setTableColumns(GPNode node, String[] propNames, boolean[] sortable) {
// this is based on the org.openide.nodes.Node.getPropertySets() method, which is filled in by the
// cern.gp.nodes.impl.BeanNode.createProperties();
// get the normal and experts propertySets and concatenate them
Node.Property[] allProperties;
PropertySet[] propSets = node.getPeerNode().getPropertySets();
Node.Property[] normalProperties = propSets[0].getProperties();
if (propSets.length == 1) {
allProperties = normalProperties;
} else {
Node.Property[] expertProperties = propSets[1].getProperties();
allProperties = new Node.Property[normalProperties.length + expertProperties.length];
System.arraycopy(normalProperties, 0, allProperties, 0, normalProperties.length);
System.arraycopy(expertProperties, 0, allProperties, normalProperties.length, expertProperties.length);
}
final Node.Property[] tableProperties;
if (propNames == null) {
tableProperties = allProperties;
} else {
ArrayList list = new ArrayList(propNames.length);
for (int n = 0; n < propNames.length; n++) {
for (int p = 0; p < allProperties.length; p++) {
if (propNames[n].equals(allProperties[p].getName())) {
list.add(allProperties[p]);
}
}
}
tableProperties = (Node.Property[]) list.toArray(new Node.Property[list.size()]);
}
tablePropertyHolder.setProperties(tableProperties, sortable);
}
/**
* helper method -- sets the table columns form an array of property descriptors
* can be made public if needed
* @deprecated -- not needed anymore, use setTableColumns(Object bean, String[] propNames)
*/
private void setTableColumns(PropertyDescriptor[] propDescriptors) {
new UnsupportedOperationException("deprecated").printStackTrace();
tablePropertyHolder.setProperties(calcNodeProperty(propDescriptors), null);
//tablePropertyHolder.setProperties(propArr);
}
/**
* @deprecated -- not needed anymore, use setTableColumns(Object bean, String[] propNames)
*/
public static Node.Property[] calcNodeProperty(PropertyDescriptor[] propDescriptors) {
Property[] propArr = new Property[propDescriptors.length];
for (int ix = 0; ix < propDescriptors.length; ix++) {
propArr[ix] = new TableViewColumnProperty(propDescriptors[ix]);
}
return propArr;
}
/**
* a helper method that determines the types of the properties by looking them up in the beanClass
* @deprecated -- not needed anymore, use setTableColumns(Object bean, String[] propNames)
*/
public static PropertyDescriptor[] calcPropertyDescriptorsFor(Class beanClass, String[] propNames)
throws IntrospectionException {
// [PENDING] we should not depend on BeanInfo here. Otheriwse NullPointerEx If someon wants to expose a column that is not declared inthe BI.
// TODO BUG: Introspector does not find the DisplayName of the properties, that's why it's missing in the Table headers
PropertyDescriptor[] propDescr = Introspector.getBeanInfo(beanClass).getPropertyDescriptors();
java.util.ArrayList listNonHidden = new java.util.ArrayList(propDescr.length);
for (int i = 0; i < propDescr.length; i++) {
if (!propDescr[i].isHidden()) {
listNonHidden.add(propDescr[i]);
}
}
propDescr = (PropertyDescriptor[]) listNonHidden.toArray(new PropertyDescriptor[listNonHidden.size()]);
if (propNames == null) {
return propDescr;
}
if (propNames.length > propDescr.length) {
System.err.println("Error: more propNames than beanClass properties!");
System.err.println("PropNames = ");
ArrayUtil.printArray(propNames, 8);
System.err.println("PropDescr = ");
ArrayUtil.printArray(propDescr, 8);
return null;
}
//PropertyDescriptor[] resultDescr = new PropertyDescriptor[propNames.length];
// find common ones:
ArrayList resultList = new ArrayList();
for (int ix = 0; ix < propNames.length; ix++) {
for (int jx = 0; jx < propDescr.length; jx++) {
if (propNames[ix].equals(propDescr[jx].getName())) {
resultList.add(propDescr[jx]);
}
}
}
return (PropertyDescriptor[]) resultList.toArray(new PropertyDescriptor[resultList.size()]);
}
/**
* Model that redirects the call to the super class if the Bean class is a subclass of
* the one set with ListTableView.setProperties().
* Otherwise it returns null. The goal is to display only the rows of the beans
* instead of creating its getPropertySets. Not used in this implementation.
* To use it, pass it as an argument to ListTableView()
*/
static class SelectiveTableModel extends NodeTableModel {
private final Class[] displayBeans;
SelectiveTableModel(Class[] displayBeans) {
this.displayBeans = displayBeans;
}
/**
* Only return valid properties if the bean corresponding to this node shall be displayed in the
* ListTable. Otherwise return null.
*/
protected Property getPropertyFor(Node node, Property prop) {
if (node instanceof GPNode) {
Class beanClass = ((GPNode) node).getBean().getClass();
for (int ix = 0; ix < displayBeans.length; ix++) {
if (displayBeans[ix].equals(beanClass)) {
return super.getPropertyFor(node, prop);
}
}
return null;
}
return super.getPropertyFor(node, prop);
}
}
/**
* dummy implementation of a Node.Property, used to tell the ListTableView what columns it
* shall display. It cannot be used to read or write properties.
*
* Instances of this class are used in the NodeTableModel.getPropertyFor() method
* @see org.openide.explorer.view.ListTableView#setProperties()
* @see org.openide.explorer.view.NodeTableModel#getPropertyFor()
*/
private static class TableViewColumnProperty extends Property {
public TableViewColumnProperty(String propertyName, String displayName, Class propertyType) {
super(propertyType);
setName(propertyName);
if (displayName != null) {
super.setDisplayName(displayName);
}
}
public TableViewColumnProperty(PropertyDescriptor prop) {
super(prop.getPropertyType());
setName(prop.getName());
if (prop.getDisplayName() != null) {
super.setDisplayName(prop.getDisplayName());
}
}
public boolean canRead() {
return false;
}
public boolean canWrite() {
return false;
}
public Object getValue() throws IllegalAccessException, InvocationTargetException {
return null;
}
public void setValue(Object obj)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
}
}
}