package org.hwo.models.TableMapper; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Hashtable; import java.util.LinkedList; import java.util.List; import javax.swing.JTable; import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; import org.hwo.csv.CSV; import org.hwo.interactiveobjects.InteractiveObjectHelper; public class TableMapper extends AbstractTableModel { private static final long serialVersionUID = -6556060772230310664L; public class ColumnInfo { private TableColumn p_annotation; private Field p_field; private Method p_method; private String p_label; private boolean p_readonly; private Class p_columnclass; private int width; private TableColumn tableColumn; private ColumnInfo nextColumn; protected ColumnInfo(TableColumn tc,Field field) { tableColumn = tc; p_annotation = field.getAnnotation(TableColumn.class); p_method = null; p_field = field; p_columnclass = field.getType(); initialize(); if (p_label.equals("")) p_label = field.getName(); field.setAccessible(true); } protected ColumnInfo(TableColumn tc,Method method) { tableColumn = tc; p_annotation = method.getAnnotation(TableColumn.class); p_method = method; p_field = null; p_columnclass = method.getReturnType(); initialize(); if (p_label.equals("")) p_label = method.getName(); method.setAccessible(true); p_readonly = true; } private void initialize() { p_label = p_annotation.label(); p_readonly = p_annotation.readonly(); setWidth(p_annotation.width()); } public void appendAtEnd(ColumnInfo column) { if (nextColumn == null) nextColumn = column; else nextColumn.appendAtEnd(column); } public List toList() { List list = new LinkedList(); appendToList(list); return list; } public void appendToList(List list) { list.add(this); if (nextColumn != null) nextColumn.appendToList(list); } public void removeColumn(ColumnInfo ci) { if (nextColumn == ci) { nextColumn = ci.nextColumn; ci.nextColumn = null; } else if (nextColumn != null) nextColumn.removeColumn(ci); } public ColumnInfo findColumnByName(String name) { if (this.p_label.equals(name)) return this; if (nextColumn!=null) return nextColumn.findColumnByName(name); else return null; } public void append(ColumnInfo ci) { ci.nextColumn = nextColumn; nextColumn = ci; } public String getLabel() { return this.p_label; } public void setLabel(String label) { this.p_label = label; } public boolean getReadOnly() { return this.p_readonly; } public void setReadOnly(boolean readOnly) { this.p_readonly = readOnly; } public void setColumnClass(Class cl) { this.p_columnclass = cl; } public Class getColumnClass() { return this.p_columnclass; } public Object getValue(Object instance) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (p_field != null) return p_field.get(instance); if (p_method != null) return p_method.invoke(instance, null); return null; } public void setValue(Object instance,Object value) throws IllegalAccessException { if (p_field != null) p_field.set(instance, value); } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public ColumnInfo getNextColumn() { return nextColumn; } public void setNextColumn(ColumnInfo nextColumn) { this.nextColumn = nextColumn; } public TableColumn getTableColumn() { return tableColumn; } public void setTableColumn(TableColumn tableColumn) { this.tableColumn = tableColumn; } } private Class p_class; private ColumnInfo firstColumn; private List p_rows; private List p_columns; private boolean p_readonly; // Table readonly... private TableMapperColumnModel columnModel; private JTable jTable; private TableMapperObject tableMapperObject; private Field editorObjectField; private Class editorObjectClass; private MouseAdapter mouseAdapter; private boolean editorEnabled; private LinkedList tableMapperListeners; public TableMapper(Class clazz,JTable table) { this.tableMapperListeners = new LinkedList(); this.p_class = clazz; this.jTable = table; this.firstColumn = null; this.p_rows = new LinkedList(); this.p_columns = new ArrayList(); this.p_readonly = false; initializeMapper(); initializeColumnInfo(); table.setModel(this); table.setColumnModel(new TableMapperColumnModel(this)); table.setAutoCreateRowSorter(true); mouseAdapter = new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { switch (e.getButton()) { case 1: if (e.getClickCount()==2) { openEditor(); } } } }; if (InteractiveObjectHelper.isInteractiveObject(editorObjectClass)) setEditorEnabled(true); } private void initializeMapper() { tableMapperObject = p_class.getAnnotation(TableMapperObject.class); if (tableMapperObject != null) { if (tableMapperObject.editorField() != null) { try { editorObjectField = p_class.getDeclaredField(tableMapperObject.editorField()); editorObjectField.setAccessible(true); editorObjectClass = editorObjectField.getType(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } else { editorObjectClass = p_class; } } public void addListSelectionListener(ListSelectionListener listener) { jTable.getSelectionModel().addListSelectionListener(listener); } public void removeListSelectionListener(ListSelectionListener listener) { jTable.getSelectionModel().removeListSelectionListener(listener); } public void addTableMapperListener(TableMapperListener listener) { tableMapperListeners.add(listener); } public void removeTableMapperListener(TableMapperListener listener) { tableMapperListeners.remove(listener); } protected void fireValueChanged(int row,int column) { for (TableMapperListener listener: tableMapperListeners) listener.ValueChanged(row, column); } private Object getEditorObject() { if (jTable.getSelectedRow()!=-1) { int row = jTable.convertRowIndexToModel(jTable.getSelectedRow()); Object rowObject = p_rows.get(row); if (editorObjectField == null) return rowObject; try { Object editorObject = editorObjectField.get(rowObject); return editorObject; } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; } private void openEditor() { Object editorObject = getEditorObject(); if (editorObject!=null) InteractiveObjectHelper.showEditor(editorObject); } public List getColumnInfo() { return p_columns; } public void setRows(List rows) { this.p_rows = rows; fireTableDataChanged(); } public List getRows() { return this.p_rows; } public List getRows(Class clazz) { return (List) p_rows; } public void clear() { this.p_rows.clear(); fireTableDataChanged(); } public boolean isEditorEnabled() { return editorEnabled; } public void setEditorEnabled(boolean enabled) { if (enabled) jTable.addMouseListener(mouseAdapter); else jTable.removeMouseListener(mouseAdapter); editorEnabled = enabled; } private void addColumnInfo(ColumnInfo ci) { if (ci.getTableColumn().firstColumn()) p_columns.add(0,ci); else p_columns.add(ci); /* if (firstColumn == null) firstColumn = ci; else { if (ci.getTableColumn().firstColumn()) { ci.setNextColumn(firstColumn); firstColumn = ci; } else firstColumn.appendAtEnd(ci); } */ } private void addFieldsOfClass(Class clazz) { if (clazz.getSuperclass() != null) addFieldsOfClass(clazz.getSuperclass()); for (Field field: clazz.getDeclaredFields()) { if (field.getAnnotation(TableColumn.class)!=null) { ColumnInfo ci = new ColumnInfo(field.getAnnotation(TableColumn.class),field); addColumnInfo(ci); } } for (Method method: clazz.getDeclaredMethods()) { if (method.getAnnotation(TableColumn.class)!=null) { ColumnInfo ci = new ColumnInfo(method.getAnnotation(TableColumn.class),method); addColumnInfo(ci); } } } private int findColumnIndexByName(String name) { for (int i=0;i lc = new ArrayList(p_columns); for (ColumnInfo ci:lc) { if (!ci.getTableColumn().after().equals("")) { int indColumn = p_columns.indexOf(ci); int indBefore = findColumnIndexByName(ci.getTableColumn().after()); if (indBefore != -1) { if (indBefore < indColumn) { List subset = new ArrayList(p_columns.subList(indColumn, p_columns.size())); p_columns.removeAll(subset); p_columns.addAll(indBefore+1, subset); } else { List subset = new ArrayList(p_columns.subList(indColumn, indBefore)); p_columns.removeAll(subset); p_columns.addAll(indColumn+1, subset); } } } } } private void initializeColumnInfo() { addFieldsOfClass(p_class); reorderColumns(); } public void setReadOnly(boolean readOnly) { this.p_readonly = readOnly; } public boolean getReadOnly() { return this.p_readonly; } public void addRow(Object row) { this.p_rows.add(row); //fireTableRowsInserted(getRowCount()-1, getRowCount()-1); fireTableDataChanged(); } public void removeRow(Object row) { int index = this.p_rows.indexOf(row); if (index != -1) { this.p_rows.remove(index); fireTableRowsDeleted(index, index); }; } public Object getRow(int index) { return this.p_rows.get(index); } public T getRow(int index,Class clazz) { return (T)this.p_rows.get(index); } public Object appendNewInstance() { try { Object instance = this.p_class.newInstance(); if (instance != null) addRow(instance); return instance; } catch (Exception ex) { return null; } } @Override public int getColumnCount() { return this.p_columns.size(); } @Override public int getRowCount() { return this.p_rows.size(); } @Override public Object getValueAt(int rowIndex, int columnIndex) { if ( (rowIndex < this.p_rows.size()) && (columnIndex < this.p_columns.size())) { try { return this.p_columns.get(columnIndex).getValue(this.p_rows.get(rowIndex)); } catch (Exception ex) { System.err.println("Exception: " + ex); ex.printStackTrace(); } } return ""; } @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { try { this.p_columns.get(columnIndex).setValue(this.p_rows.get(rowIndex), aValue); fireValueChanged(rowIndex, columnIndex); } catch (IllegalAccessException ex) { System.err.println("IllegalAccessException: " + ex); ex.printStackTrace(); } } @Override public boolean isCellEditable(int rowIndex,int columnIndex) { if (this.p_readonly) return false; return !this.p_columns.get(columnIndex).getReadOnly(); } @Override public Class getColumnClass(int columnIndex) { Class c = this.p_columns.get(columnIndex).getColumnClass(); return c; } @Override public String getColumnName(int columnIndex) { return this.p_columns.get(columnIndex).getLabel(); } public Object getSelectedRow() { if (jTable.getSelectedRow()!=-1) { return this.p_rows.get(jTable.convertRowIndexToModel(jTable.getSelectedRow())); } return null; } public boolean exportToFile(File exportFile) { CSV csv = new CSV(); List cells = csv.getCells(); String[] header = new String[ getColumnCount() ]; for (int i=0;i