java-org.hwo/src/org/hwo/models/TableMapper/TableMapper.java

638 lines
13 KiB
Java

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<ColumnInfo> toList()
{
List<ColumnInfo> list = new LinkedList<TableMapper.ColumnInfo>();
appendToList(list);
return list;
}
public void appendToList(List<ColumnInfo> 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<Object> p_rows;
private List<ColumnInfo> 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<TableMapperListener> tableMapperListeners;
public TableMapper(Class<?> clazz,JTable table)
{
this.tableMapperListeners = new LinkedList<TableMapperListener>();
this.p_class = clazz;
this.jTable = table;
this.firstColumn = null;
this.p_rows = new LinkedList<Object>();
this.p_columns = new ArrayList<TableMapper.ColumnInfo>();
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<ColumnInfo> getColumnInfo()
{
return p_columns;
}
public void setRows(List rows)
{
this.p_rows = rows;
fireTableDataChanged();
}
public List getRows()
{
return this.p_rows;
}
public <T> List<T> getRows(Class<T> clazz)
{
return (List<T>) 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<p_columns.size();i++)
{
if (p_columns.get(i).p_label.equals(name))
return i;
}
return -1;
}
private void reorderColumns()
{
List<ColumnInfo> lc = new ArrayList<TableMapper.ColumnInfo>(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<ColumnInfo> subset = new ArrayList<TableMapper.ColumnInfo>(p_columns.subList(indColumn, p_columns.size()));
p_columns.removeAll(subset);
p_columns.addAll(indBefore+1, subset);
} else
{
List<ColumnInfo> subset = new ArrayList<TableMapper.ColumnInfo>(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> T getRow(int index,Class<T> 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<String[]> cells = csv.getCells();
String[] header = new String[ getColumnCount() ];
for (int i=0;i<getColumnCount();i++)
header[i] = p_columns.get(i).getLabel();
cells.add( header );
for (int row=0;row<getRowCount();row++)
{
String[] record = new String[ getColumnCount() ];
for (int column=0;column<getColumnCount();column++)
if (getValueAt(row, column)!=null)
record[column] = getValueAt(row, column).toString();
else
record[column] = "";
cells.add(record);
}
csv.saveToFile(exportFile);
return true;
}
};