package com.quantum.model; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import com.quantum.adapters.DatabaseAdapter; /** * This class models a table or view. * * @author bcholmes */ abstract class EntityImpl implements Entity { private String schema; private String name; private String type; private Bookmark bookmark; private Boolean exists = Boolean.TRUE; public EntityImpl(Bookmark bookmark, String schema, String name, String type) { this.schema = schema; this.name = name; this.type = type; this.bookmark = bookmark; } public Bookmark getBookmark() { return this.bookmark; } public String getName() { return this.name; } public String getSchema() { return this.schema; } public String getType() { return this.type; } public String getQualifiedName() { return (this.schema == null || this.schema.length() == 0) ? this.name : this.schema + "." + this.name; } public Column getColumn(String columnName) throws NotConnectedException, SQLException { Column column = null; Column[] columns = getColumns(); for (int i = 0, length = (columns == null) ? 0 : columns.length; column == null && i < length; i++) { if (columnName != null && columnName.equals(columns[i].getName())) { column = columns[i]; } } return column; } public Column[] getColumns() throws NotConnectedException, SQLException { Map temp = new HashMap(); Connection connection = this.bookmark.getConnection(); DatabaseMetaData metaData = connection.getMetaData(); ResultSet resultSet = metaData.getColumns(null, getSchema(), getName(), null); try { while (resultSet.next()) { ColumnImpl column = new ColumnImpl( this, resultSet.getString("COLUMN_NAME"), resultSet.getString("TYPE_NAME"), resultSet.getInt("DATA_TYPE"), resultSet.getInt("COLUMN_SIZE"), resultSet.getInt("DECIMAL_DIGITS"), "YES".equalsIgnoreCase(resultSet.getString("IS_NULLABLE")), resultSet.getInt("ORDINAL_POSITION"), getComments(resultSet.getString("REMARKS"),getQualifiedName(), resultSet.getString("COLUMN_NAME")) ); temp.put(column.getName(), column); } } finally { resultSet.close(); } resultSet = metaData.getPrimaryKeys(null, getSchema(), getName()); try { while (resultSet.next()) { String name = resultSet.getString("COLUMN_NAME"); short keySequence = resultSet.getShort("KEY_SEQ"); ColumnImpl column = (ColumnImpl) temp.get(name); if (column != null) { column.setPrimaryKeyOrder(keySequence); } } resultSet.close(); List columnList = Collections.synchronizedList( new ArrayList(temp.values())); Collections.sort(columnList); return (Column[]) columnList.toArray(new Column[columnList.size()]); } finally { resultSet.close(); } } /** * Some JDBC drivers (Oracle for example) won't return the comments * We recheck with a custom query, if it's defined * @param iniComment The already got comment * @param tableName The fully qualified table name * @param columnName The column name */ private String getComments( String iniComment, String tableName, String columnName) { if (iniComment != null && iniComment.length() > 0) return iniComment; String comment = ""; try { Connection con = this.bookmark.getConnection(); Statement stmt = con.createStatement(); DatabaseAdapter adapter = this.bookmark.getAdapter(); if (adapter != null && stmt != null && adapter.getCommentsQuery(tableName, columnName) != null) { stmt.execute(adapter.getCommentsQuery(tableName, columnName)); ResultSet set = stmt.getResultSet(); if (set.next()) comment = set.getString(1); } } catch (NotConnectedException e) { } catch (SQLException e) { } return comment; } public Index[] getIndexes() { List indexList = new ArrayList(); Map temp = new HashMap(); try { Connection connection = this.bookmark.getConnection(); DatabaseMetaData metaData = connection.getMetaData(); ResultSet resultSet = metaData.getIndexInfo(null, getSchema(), getName(), false, false); while (resultSet.next()) { String indexName = resultSet.getString("INDEX_NAME"); IndexImpl index = (IndexImpl) temp.get(indexName); if (index == null) { index = new IndexImpl(this, indexName); temp.put(indexName, index); } String columnName = resultSet.getString("COLUMN_NAME"); String ascending = resultSet.getString("ASC_OR_DESC"); index.addColumn(columnName, ascending == null ? null : (ascending.toUpperCase().startsWith("A") ? Boolean.TRUE : Boolean.FALSE)); } resultSet.close(); indexList.addAll(temp.values()); } catch (NotConnectedException e) { } catch (SQLException e) { } return (Index[]) indexList.toArray(new Index[indexList.size()]); } public Boolean exists() { return this.exists; } /** * @see com.quantum.model.Entity#getQuotedTableName() */ public String getQuotedTableName() { return getBookmark().getAdapter().filterTableName(getQualifiedName()); } public ForeignKey[] getExportedKeys() throws SQLException, NotConnectedException { return this.bookmark.getDatabase().getExportedKeys(getSchema(), getName()); } public ForeignKey[] getImportedKeys() throws SQLException, NotConnectedException { return this.bookmark.getDatabase().getImportedKeys(getSchema(), getName()); } public ForeignKey[] getReferences() throws SQLException, NotConnectedException { ForeignKey[] importedKeys = getImportedKeys(); ForeignKey[] exportedKeys = getExportedKeys(); List list = new ArrayList(); // if we could guarantee JDK 1.4, we'd use LinkedHashSet for (int i = 0, length = importedKeys == null ? 0 : importedKeys.length; i < length; i++) { list.add(importedKeys[i]); } for (int i = 0, length = exportedKeys == null ? 0 : exportedKeys.length; i < length; i++) { if (!list.contains(exportedKeys[i])) { list.add(exportedKeys[i]); } } return (ForeignKey[]) list.toArray(new ForeignKey[list.size()]); } public int compareTo(Object object) { Entity that = (Entity) object; if (that.getQualifiedName() == null && this.getQualifiedName() != null) { return 1; } else if (this.getQualifiedName() == null && that.getQualifiedName() != null) { return -1; } else if (this.getQualifiedName() == null && that.getQualifiedName() == null) { return 0; } else { return this.getQualifiedName().compareTo(that.getQualifiedName()); } } }