// Beispielklasse aus dem JavaTutorial (http://java.sun.com/docs/books/tutorial) für SuperX angepasst /* * @(#)JDBCAdapter.java 1.5 97/12/03 * * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved. * * This software is the confidential and proprietary information of Sun * Microsystems, Inc. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. * */ /** * An adaptor, transforming the JDBC interface to the TableModel interface. * * @version 1.20 09/25/97 * @author Philip Milne */ package de.superx.applet; import java.math.BigDecimal; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Timestamp; import java.sql.Types; import java.text.NumberFormat; import java.text.ParseException; import java.util.Properties; import java.util.Vector; import javax.swing.table.AbstractTableModel; import de.superx.common.SuperX_el; /** * Ein Adapter, der das JDBC-Interface an das TableModel-Interface anpasst. * Angepasst für SuperX * @autor Philip Milne, erweitert von R. Behr * @version 1.2 */ public class SxJDBCAdapter extends AbstractTableModel implements SxTableModel { Connection connection; Properties db_props = null; boolean isClosed = true; boolean isEditable = false; Statement statement = null; ResultSet resultSet = null; String[] columnNames = {}; Class[] columnTpyes = {}; Vector rows = new Vector(); SxSQLMetaData metaData; NumberFormat nf = NumberFormat.getInstance(); //DecimalFormat df=(DecimalFormat) nf; /* public SxJDBCAdapter(String url, String driverName, String user, String passwd) throws Exception { try { Class.forName(driverName); System.err.println("Opening db connection"); if (!isClosed) { statement.close(); connection.close (); isClosed = true; } db_props = new Properties (); db_props.put ("user", user); db_props.put ("password", passwd); connection = DriverManager.getConnection(url, db_props); statement = connection.createStatement(); isClosed = false; } catch (Exception ex) { isClosed = true; throw new SQLException (ex.toString()); } }*/ public SxJDBCAdapter() {} public void executeQuery(String query) throws SQLException { resultSet = statement.executeQuery(query); // resultSet = statement.getResultSet(); metaData = new SxSQLMetaData (new SuperX_el()); //metaData = resultSet.getMetaData(); int numberOfColumns = metaData.getColumnCount(); columnNames = new String[numberOfColumns]; // Get the column names and cache them. // Then we can close the connection. for(int column = 0; column < numberOfColumns; column++) { columnNames[column] = metaData.getColumnLabel(column+1); // System.err.println ("Column: " + columnNames[column] + ", max width: " + // metaData.getColumnDisplaySize(column+1)); } // Get all rows. rows = new Vector(); while (resultSet.next()) { Vector newRow = new Vector(); for (int i = 0; i < getColumnCount(); i++) { // newRow.addElement(dbRepresentation(i, resultSet.getObject(i + 1))); newRow.addElement(resultSet.getObject(i + 1)); } rows.addElement(newRow); } // close(); // Need to copy the metaData, bug in jdbc:odbc driver. fireTableChanged(null); // Tell the listeners a new table has arrived. } public void cancel(String url, String user, String passwd) throws Exception { try { System.err.println("Cancel statement"); statement.cancel(); } catch (Exception e) { System.err.println("Error canceling statement: " + e); } } public void close() throws SQLException { try { System.err.println("Closing db connection"); if (!isClosed) { if (resultSet != null) resultSet.close(); if (statement != null) statement.close(); connection.close(); isClosed = true; } } catch (SQLException e) { System.err.println("Error closing db connection: " + e); } } protected void finalize() throws Throwable { if (!isClosed) { close(); isClosed = true; } super.finalize(); } ////////////////////////////////////////////////////////////////////////// // // Implementation des TableModelInterface // ////////////////////////////////////////////////////////////////////////// // MetaData public String getColumnName(int column) { if (columnNames[column] != null) { return columnNames[column]; } else { return ""; } } public int getColumnSize(int column) { if (metaData == null) return -1; return metaData.getColumnDisplaySize(column+1); } public Class getColumnClass(int column) { int type; if (metaData == null) return Object.class; type = metaData.getColumnType(column+1); switch(type) { case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: return String.class; case Types.BIT: return Boolean.class; case Types.TINYINT: case Types.SMALLINT: return Short.class; case Types.INTEGER: return Integer.class; case Types.BIGINT: return Long.class; case Types.FLOAT: case Types.DOUBLE: return Double.class; case Types.DATE: return java.sql.Date.class; case Types.DECIMAL: case Types.NUMERIC: return java.math.BigDecimal.class; case Types.TIMESTAMP: return java.sql.Timestamp.class; default: return Object.class; } } public void setEditable(boolean editable) { isEditable = editable; } public boolean isCellEditable(int row, int column) { if (isEditable) return metaData.isWritable(column); else return false; } public int getColumnCount() { return columnNames.length; } // Data methods public int getRowCount() { return rows.size(); } public Object getValueAt(int aRow, int aColumn) { Vector row = (Vector)rows.elementAt(aRow); Object value = row.elementAt(aColumn); return dbRepresentation(aColumn, value, true); } public Object getObjectAt(int aRow, int aColumn) { Vector row = (Vector)rows.elementAt(aRow); return row.elementAt(aColumn); } private String dbRepresentation(int column, Object value, boolean isDecimalParsingWanted) { int type; int scale; double db; String str; if (metaData == null) return value.toString(); if (value == null||value.equals("")) return " "; type = metaData.getColumnType(column+1); scale = metaData.getScale(column+1); switch(type) { case Types.SMALLINT: int int_value = Short.MIN_VALUE; if (value instanceof Short) int_value = ((Short) value).shortValue(); else if (value instanceof Integer) int_value = ((Integer) value).intValue(); if (int_value == Short.MIN_VALUE) return (" "); return value.toString(); case Types.INTEGER: if (!(value instanceof Integer)) return value.toString(); if (((Integer) value).intValue() == Integer.MIN_VALUE) return (" "); return value.toString(); case Types.DOUBLE: if (isDecimalParsingWanted) { if (((Double) value).isNaN()) return " "; nf.setMinimumFractionDigits(scale); // r.b. Nachkommastellen setzen nf.setGroupingUsed(true); //df.setDecimalSeparatorAlwaysShown(true); //df.applyLocalizedPattern("#.#00,0#"); if (scale > 3) nf.setMaximumFractionDigits(3); // r.b. Nachkommastellen setzen return nf.format((Double) value); } else return value.toString(); case Types.DECIMAL: case Types.NUMERIC: if (isDecimalParsingWanted) { db = ((BigDecimal) value).doubleValue(); nf.setGroupingUsed(true); if (db == Double.NaN) return " "; //MB bigdecimal kann immer >65000 Nachkommastellen haben, wird immer auf 5 gesetzt //bei Studiabfragen nach Abschlüssen, ist wahrscheinlich ganz gut, dass ,00 verschwindet (wenngleich gewichtete Fälle) //bei Cob abfragen wäre schön //if (scale > 5) nf.setMaximumFractionDigits(5); // r.b. Nachkommastellen setzen //else nf.setMinimumFractionDigits(scale); // r.b. Nachkommastellen setzen //, einfach mal fest von 2 ausgehen nf.setMaximumFractionDigits(2); nf.setMinimumFractionDigits(2); //df.setDecimalSeparatorAlwaysShown(true); //df.applyLocalizedPattern("#.#00,0#"); return nf.format(db); } else return value.toString(); case Types.BIT: return ((Boolean)value).booleanValue() ? "1" : "0"; case Types.DATE: str = SxDate.toString((java.sql.Date) value); if (str.length() == 0) return (" "); return str; case Types.TIMESTAMP: str = ((Timestamp) value).toString(); if (str.length() == 0) return (" "); return str; default: if (value.toString().length() == 0) return (" "); return value.toString(); } } private Object tableRepresentation(int column, Object value) { int type; if (value == null) { return ""; } if (metaData == null) return value; type = metaData.getColumnType(column+1); switch(type) { case Types.SMALLINT: { try { return new Short (value.toString()); } catch (NumberFormatException e) { System.err.println ("tableRepresentation: ERROR: " + value.toString()); return ""; } } case Types.INTEGER: { try { return new Integer (value.toString()); } catch (NumberFormatException e) { System.err.println ("tableRepresentation: ERROR: " + value.toString()); return ""; } } case Types.DOUBLE: case Types.FLOAT: { try { Number new_number = nf.parse(value.toString()); Double new_double = new Double(new_number.doubleValue()); return new_double; } catch (ParseException e) { System.err.println ("tableRepresentation: ERROR parse: Double=" + value.toString()); return ""; } } case Types.DECIMAL: { try { Number new_number = nf.parse(value.toString()); BigDecimal new_dec = new BigDecimal(new_number.doubleValue()); return new_dec; } catch (ParseException e) { System.err.println ("tableRepresentation: ERROR parse: BigDecimal=" + value.toString()); return ""; } } case Types.BIT: return new Boolean (value.toString()); case Types.DATE: return SxDate.getDate(value.toString()); case Types.TIMESTAMP: return Timestamp.valueOf(value.toString()); default: return value; } } public void setValueAt(Object value, int row, int column) { try { String tableName = "info_usr"; // r.b. metaData.getTableName(column+1); // Some of the drivers seem buggy, tableName should not be null. if (tableName == null) { System.err.println("Table name returned null."); } String colName = getColumnName(column); Object new_value = tableRepresentation(column, value); if (new_value == null) throw new SQLException ("conversion error"); System.err.println ("column: " + colName + ", value: " + new_value); String query = "update "+tableName+ " set "+colName+" = " + "'" + dbRepresentation(column, new_value, true) + "'" + " where "; // We don't have a model of the schema so we don't know the // primary keys or which columns to lock on. To demonstrate // that editing is possible, we'll just lock on everything. for(int col = 0; col