package org.openswing.swing.pivottable.tablemodelreaders.server; import java.util.*; import javax.swing.event.*; import javax.swing.table.*; import java.lang.reflect.Method; import org.openswing.swing.message.receive.java.ValueObject; import java.math.BigDecimal; import javax.swing.ImageIcon; import javax.swing.Icon; /** * <p>Title: OpenSwing Framework</p> * <p>Description: TableModel implementation, based on a list of ValueObjects.</p> * <p>Copyright: Copyright (C) 2006 Mauro Carniel</p> * * <p> This file is part of OpenSwing Framework. * This library is free software; you can redistribute it and/or * modify it under the terms of the (LGPL) Lesser General Public * License as published by the Free Software Foundation; * * GNU LESSER GENERAL PUBLIC LICENSE * Version 2.1, February 1999 * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * The author may be contacted at: * maurocarniel@tin.it</p> * * @author Mauro Carniel * @version 1.0 */ public class VOTableModel extends AbstractTableModel { /** list of ValueObjects */ private List valueObjects; /** ValueObject setter methods */ private Hashtable voSetterMethods = new Hashtable(); /** ValueObject getter methods */ private Hashtable voGetterMethods = new Hashtable(); /** ValueObject type */ private Class valueObjectType = null; /** collection of couples: related attribute (String), column model index (Integer) */ private Hashtable reverseIndexes = new Hashtable(); /** attribute names */ private String[] attributeNames = null; /** * Constructs a TableModel, starting from the specified list of ValueObjects, having the specified list of attributes * @param valueObjects list of ValueObjects * @param attributeNames nome of attributes defined within the ValueObjects, used to define the TableModel */ public VOTableModel(List valueObjects,String[] attributeNames) { this.valueObjects = valueObjects; this.attributeNames = attributeNames; this.valueObjectType = valueObjects.get(0).getClass(); analyzeClassFields(new Hashtable(),"",new Method[0],valueObjectType); } /** * @param row row number * @return ValueObject */ public final ValueObject getValueObject(int row) { return (ValueObject)valueObjects.get(row); } /** * Analyze class fields and fill in "voSetterMethods","voGetterMethods","indexes",reverseIndexes" attributes. * @param prefix e.g. "attrx.attry." * @param parentMethods getter methods of parent v.o. * @param classType class to analyze */ private void analyzeClassFields(Hashtable vosAlreadyProcessed,String prefix,Method[] parentMethods,Class classType) { try { Integer num = (Integer)vosAlreadyProcessed.get(classType); if (num==null) num = new Integer(0); num = new Integer(num.intValue()+1); if (num.intValue()>10) return; vosAlreadyProcessed.put(classType,num); // retrieve all getter and setter methods defined in the specified value object... String attributeName = null; Method[] methods = classType.getMethods(); String aName = null; for(int i=0;i<methods.length;i++) { attributeName = methods[i].getName(); if (attributeName.startsWith("get") && methods[i].getParameterTypes().length==0 && ValueObject.class.isAssignableFrom(methods[i].getReturnType())) { aName = getAttributeName(attributeName,classType); Method[] newparentMethods = new Method[parentMethods.length+1]; System.arraycopy(parentMethods,0,newparentMethods,0,parentMethods.length); newparentMethods[parentMethods.length] = methods[i]; analyzeClassFields(vosAlreadyProcessed,prefix+aName+".",newparentMethods,methods[i].getReturnType()); } if (attributeName.startsWith("get") && methods[i].getParameterTypes().length==0 && (methods[i].getReturnType().equals(String.class) || methods[i].getReturnType().equals(Long.class) || methods[i].getReturnType().equals(Long.TYPE) || methods[i].getReturnType().equals(Float.class) || methods[i].getReturnType().equals(Float.TYPE) || methods[i].getReturnType().equals(Short.class) || methods[i].getReturnType().equals(Short.TYPE) || methods[i].getReturnType().equals(Double.class) || methods[i].getReturnType().equals(Double.TYPE) || methods[i].getReturnType().equals(BigDecimal.class) || methods[i].getReturnType().equals(java.util.Date.class) || methods[i].getReturnType().equals(java.sql.Date.class) || methods[i].getReturnType().equals(java.sql.Timestamp.class) || methods[i].getReturnType().equals(Integer.class) || methods[i].getReturnType().equals(Integer.TYPE) || methods[i].getReturnType().equals(Character.class) || methods[i].getReturnType().equals(Boolean.class) || methods[i].getReturnType().equals(boolean.class) || methods[i].getReturnType().equals(ImageIcon.class) || methods[i].getReturnType().equals(Icon.class) || methods[i].getReturnType().equals(byte[].class) || methods[i].getReturnType().equals(Object.class) || ValueObject.class.isAssignableFrom( methods[i].getReturnType() ) )) { attributeName = getAttributeName(attributeName,classType); // try { // if (classType.getMethod("set"+attributeName.substring(0,1).toUpperCase()+attributeName.substring(1),new Class[]{methods[i].getReturnType()})!=null) Method[] newparentMethods = new Method[parentMethods.length+1]; System.arraycopy(parentMethods,0,newparentMethods,0,parentMethods.length); newparentMethods[parentMethods.length] = methods[i]; voGetterMethods.put(prefix+attributeName,newparentMethods); // } catch (NoSuchMethodException ex) { // } } else if (attributeName.startsWith("is") && methods[i].getParameterTypes().length==0 && (methods[i].getReturnType().equals(Boolean.class) || methods[i].getReturnType().equals(boolean.class) )) { attributeName = getAttributeName(attributeName,classType); Method[] newparentMethods = new Method[parentMethods.length+1]; System.arraycopy(parentMethods,0,newparentMethods,0,parentMethods.length); newparentMethods[parentMethods.length] = methods[i]; voGetterMethods.put(prefix+attributeName,newparentMethods); } else if (attributeName.startsWith("set") && methods[i].getParameterTypes().length==1) { attributeName = getAttributeName(attributeName,classType); try { if (classType.getMethod("get"+attributeName.substring(0,1).toUpperCase()+attributeName.substring(1),new Class[0])!=null) { Method[] newparentMethods = new Method[parentMethods.length+1]; System.arraycopy(parentMethods,0,newparentMethods,0,parentMethods.length); newparentMethods[parentMethods.length] = methods[i]; voSetterMethods.put(prefix+attributeName,newparentMethods); } } catch (NoSuchMethodException ex) { try { if (classType.getMethod("is"+attributeName.substring(0,1).toUpperCase()+attributeName.substring(1),new Class[0])!=null) { Method[] newparentMethods = new Method[parentMethods.length+1]; System.arraycopy(parentMethods,0,newparentMethods,0,parentMethods.length); newparentMethods[parentMethods.length] = methods[i]; voSetterMethods.put(prefix+attributeName,newparentMethods); } } catch (NoSuchMethodException exx) { } } } } // fill in indexes with the colProperties indexes first; after them, it will be added the other indexes (of attributes not mapped with grid column...) HashSet alreadyAdded = new HashSet(); int i=0; for(i=0;i<attributeNames.length;i++) { reverseIndexes.put(attributeNames[i],new Integer(i)); alreadyAdded.add(attributeNames[i]); } Enumeration en = voGetterMethods.keys(); while(en.hasMoreElements()) { attributeName = en.nextElement().toString(); if (!alreadyAdded.contains(attributeName)) { reverseIndexes.put(attributeName,new Integer(i)); i++; } } } catch (Exception ex) { ex.printStackTrace(); } } /** * @param methodName getter method * @param clazz value object class * @return attribute name related to the specified getter method */ private String getAttributeName(String methodName,Class classType) { String attributeName = null; if (methodName.startsWith("is")) attributeName = methodName.substring(2,3).toLowerCase()+(methodName.length()>3?methodName.substring(3):""); else attributeName = methodName.substring(3,4).toLowerCase()+(methodName.length()>4?methodName.substring(4):""); // an attribute name "Xxxx" becomes "xxxx" and this is not correct! try { Class c = classType; boolean attributeFound = false; while(!c.equals(Object.class)) { try { c.getDeclaredField(attributeName); attributeFound = true; break; } catch (Throwable ex2) { c = c.getSuperclass(); } } if (!attributeFound) { // now trying to find an attribute having the first character in upper case (e.g. "Xxxx") String name = attributeName.substring(0,1).toUpperCase()+attributeName.substring(1); c = classType; while(!c.equals(Object.class)) { try { c.getDeclaredField(name); attributeFound = true; break; } catch (Throwable ex2) { c = c.getSuperclass(); } } if (attributeFound) attributeName = name; } } catch (Throwable ex1) { } return attributeName; } public final int getColumnCount() { return attributeNames.length; } public final int getRowCount() { return valueObjects.size(); } public final boolean isCellEditable(int rowIndex, int columnIndex) { return false; } public final Class getColumnClass(int columnIndex) { try { Method[] m = (Method[])voGetterMethods.get(attributeNames[columnIndex]); return m[m.length-1].getReturnType(); } catch (Exception ex) { ex.printStackTrace(); return String.class; } } public final Object getValueAt(int rowIndex, int colIndex) { try { Method[] m = (Method[])voGetterMethods.get(attributeNames[colIndex]); Object obj = valueObjects.get(rowIndex); for(int i=0;i<m.length-1;i++){ obj = (ValueObject)m[i].invoke(obj,new Object[0]); if(obj == null) { return null; } } return m[m.length-1].invoke(obj,new Object[0]); } catch (Exception ex) { ex.printStackTrace(); return null; } } /** * setValueAt * * @param aValue Object * @param rowIndex int * @param columnIndex int */ public final void setValueAt(Object aValue, int rowIndex, int columnIndex) { throw new UnsupportedOperationException("TableModel is read only."); } /** * getColumnName * * @param columnIndex int * @return String */ public final String getColumnName(int columnIndex) { return attributeNames[columnIndex]; } }