import javax.swing.table.AbstractTableModel; import java.util.Vector; /** * MasterSet wraps dataset with table model and access methods. * @author Lars Appel * @version 0.2 */ public class MasterSet extends AbstractTableModel { /** * We use a Vector of String[] tuples for memory storage. * * To simplify this example, the whole dataset is fetched by * the client. For real life usage, some bulk fetch with row * limit would be required to avoid pulling a large dataset * into the client. Better use "page by page" scrolling row * buffer in those cases. */ Vector myTable; /** * List columns are defined by a String[] of column names. */ String[] listColumnNames; /** * Column widths are needed to parse the server retrievals. */ int[] listColumnWidths; /* * The standard TableModel methods follow. */ public int getRowCount() { return myTable.size(); } public int getColumnCount() { return listColumnNames.length; } public String getColumnName(int columnIndex) { return listColumnNames[columnIndex]; } public Object getValueAt(int row, int column) { return ((String[]) myTable.elementAt(row))[column]; } /** * Constructor defines the column names, widths, prompts, * as well as server prompt and server control commands. */ MasterSet( // list view String[] columnNames, // column headings shown in table int[] columnWidths, // for parsing server retrieval // entry view String[] fieldNames, // for the GUI dialog labels int[] fieldWidths, // for the GUI dialog fields String[] columnPrompts, // server prompts for add/update int[] columnsInList, // fields also shown in list view // common HostIO host, // the server stdio connection String prompt, // the server's command prompt String fetchList, // command to retrieve the list String fetchData, // command to retrieve an entry String addEntry, // command to add an entry String updateEntry, // command to update an entry String deleteEntry // command to delete an entry ) { super(); myTable = new Vector(); listColumnNames = columnNames; listColumnWidths = columnWidths; entryFieldNames = fieldNames; entryFieldWidths = fieldWidths; entryColumnPrompts = columnPrompts; entryColumnsInList = columnsInList; this.host = host; this.prompt = prompt; fetchListCmd = fetchList; fetchDataCmd = fetchData; addEntryCmd = addEntry; updateEntryCmd = updateEntry; deleteEntryCmd = deleteEntry; } HostIO host; String prompt; String fetchListCmd; String fetchDataCmd; String addEntryCmd; String updateEntryCmd; String deleteEntryCmd; String[] entryFieldNames; int[] entryFieldWidths; /** * Provide entry field names to the GUI components. */ String[] getFieldNames() { return entryFieldNames; } /** * Provide entry field widths to the GUI components. */ int[] getFieldWidths() { return entryFieldWidths; } /** * Fetch the list of entries from host by sending an appropriate * command in response to the expected prompt and parse the returned * lines until a blank line is seen (which ends the result output). */ public void fetchList() { myTable.removeAllElements(); host.answerTo(prompt, fetchListCmd); host.skipLines(1); // the echo while (host.readln().length() > 1) { String[] myRow = new String[listColumnWidths.length]; String hostLine = host.getLine(); int pos = 0; // parsing cursor for (int col=0; col < myRow.length; col++) { if (pos >= hostLine.length()) { myRow[col] = ""; } else { int pos2 = pos + listColumnWidths[col]; if (pos2 > hostLine.length()) { myRow[col] = hostLine.substring(pos).trim(); } else { myRow[col] = hostLine.substring(pos, pos2).trim(); } } pos = pos + listColumnWidths[col] + 1; // assume 1 space } myTable.addElement(myRow); } fireTableDataChanged(); } /** * Column prompts are needed to parse the server retrievals. */ String[] entryColumnPrompts; /** * Retrieve an entry from the server given its key column value. * We assume that column 0 of tuples is the unique master key. */ public String[] fetchData(String keyValue) { host.answerTo(prompt, fetchDataCmd); host.answerTo(entryColumnPrompts[0], keyValue); host.skipLines(1); // echo String[] tuple = new String[entryColumnPrompts.length]; tuple[0] = keyValue; for (int k=1; k < tuple.length; k++) { tuple[k] = host.readln().trim(); } return tuple; } /** * Which columns of an entry are to be shown in the list view? */ int[] entryColumnsInList; /** * Add an entry to the server database and myTable as well. * @return Error message or null. */ String addEntry(String[] tuple) { host.answerTo(prompt, addEntryCmd); for (int k=0; k < entryColumnPrompts.length; k++) { host.answerTo(entryColumnPrompts[k], tuple[k]); } host.skipLines(1); // last echo if (host.readln().indexOf("FAILED") >= 0) { return host.getLine(); } else { host.pushBack(); String[] myRow = new String[entryColumnsInList.length]; for (int k=0; k < entryColumnsInList.length; k++) { myRow[k] = tuple[entryColumnsInList[k]]; } myTable.addElement(myRow); fireTableRowsInserted(myTable.size()-1, myTable.size()-1); return null; } } /** * Update an entry in the server database and myTable as well. * We assume that column 0 of tuples is the unique master key. * @return Error message or null. */ public String updateEntry(int row, String[] tuple) { host.answerTo(prompt, updateEntryCmd); host.answerTo(entryColumnPrompts[0], tuple[0]); host.skipLines(1); // echo if (host.readln().indexOf("FAILED") >= 0) { return host.getLine(); } else { host.pushBack(); for (int k=1; k < entryColumnPrompts.length; k++) { host.answerTo(entryColumnPrompts[k], tuple[k]); } host.skipLines(1); // last echo if (host.readln().indexOf("FAILED") >= 0) { return host.getLine(); } else { host.pushBack(); String[] myRow = (String[]) myTable.elementAt(row); for (int k=0; k < entryColumnsInList.length; k++) { myRow[k] = tuple[entryColumnsInList[k]]; } fireTableRowsUpdated(row, row); return null; } } } /** * Delete an entry in the server database and myTable as well. * We assume that column 0 of tuples is the unique master key. * @return Error message or null. */ public String deleteEntry(int row, String keyValue) { host.answerTo(prompt, deleteEntryCmd); host.answerTo(entryColumnPrompts[0], keyValue); host.skipLines(1); // echo if (host.readln().indexOf("FAILED") >= 0) { return host.getLine(); } else { host.pushBack(); myTable.removeElementAt(row); fireTableRowsDeleted(row, row); return null; } } }