/* * Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation * Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber * All Rights Reserved * * This software is licensed under the Berkeley Standard Distribution license, * (BSD license), as defined below: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of Israfil Consulting Services nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * $Id: MockResultSetMetaData.java 13 2006-01-27 23:45:36Z cgruber $ */ package net.israfil.foundation.mock.sql; import java.math.BigDecimal; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Timestamp; import java.sql.Types; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * An implementation of DatabaseMetaData that partners with ResultSet to * provide database-disconnected fixed results for testing via the JDBC * APIs. * * @author Christian Edward Gruber */ public class MockResultSetMetaData implements ResultSetMetaData { public static int ZERO_ORDER_LIST_OFFSET = 1; List columns; MockResultSetMetaData(String ... columns) { if (columns == null) throw new IllegalArgumentException("Cannot construct a MockResultSet with no columns."); ColSpec[] colspecs = new ColSpec[columns.length]; for (int i = 0 ; i < columns.length ; i++) { colspecs[i] = new ColSpec(columns[i]); } prepColumns(colspecs); } MockResultSetMetaData(ColSpec ... columns) { prepColumns(columns); } private void prepColumns(ColSpec ... columns) { if (columns == null || columns.length <= 0) throw new IllegalArgumentException("Cannot construct a MockResultSet with no columns."); this.columns = new ArrayList(Arrays.asList(columns)); } public void finalize() throws Throwable { columns = null; } /** * Given a column name, this method returns the number of the column, or 0 if * no such column exists. * * @param name * @return */ public int getColumnNumber(String name) { for (int i = 1; i <= columns.size(); i++) if (columns.get(i-ZERO_ORDER_LIST_OFFSET).name.equalsIgnoreCase(name)) return i; return 0; } public String getCatalogName(int column) throws SQLException { return ""; } public String getColumnClassName(int column) throws SQLException { throw new UnsupportedOperationException("Not yet implemented."); } public int getColumnCount() throws SQLException { return columns.size(); } public int getColumnDisplaySize(int column) throws SQLException { return columns.get(column-ZERO_ORDER_LIST_OFFSET).width; } public String getColumnLabel(int column) throws SQLException { if (column < 1) throw new IllegalArgumentException("Column number must be greater than 0."); return columns.get(column-ZERO_ORDER_LIST_OFFSET).name; } public String getColumnName(int column) throws SQLException { if (column < 1) throw new IllegalArgumentException("Column number must be greater than 0."); return columns.get(column-ZERO_ORDER_LIST_OFFSET).name; } public int getColumnType(int column) throws SQLException { return columns.get(column-ZERO_ORDER_LIST_OFFSET).type.sqltype; } public String getColumnTypeName(int column) throws SQLException { return columns.get(column).type.name(); } public int getPrecision(int column) throws SQLException { return columns.get(column-ZERO_ORDER_LIST_OFFSET).precision; } public int getScale(int column) throws SQLException { return columns.get(column-ZERO_ORDER_LIST_OFFSET).scale; } public String getSchemaName(int column) throws SQLException { return ""; } public String getTableName(int column) throws SQLException { return ""; } public boolean isAutoIncrement(int column) throws SQLException { return false; } public boolean isCaseSensitive(int column) throws SQLException { return false; } public boolean isCurrency(int column) throws SQLException { return false; } public boolean isDefinitelyWritable(int column) throws SQLException { throw new UnsupportedOperationException("Not yet implemented."); } public int isNullable(int column) throws SQLException { return columns.get(column-ZERO_ORDER_LIST_OFFSET).nullable ? ResultSetMetaData.columnNullable : ResultSetMetaData.columnNoNulls; } public boolean isReadOnly(int column) throws SQLException { return true; } public boolean isSearchable(int column) throws SQLException { throw new UnsupportedOperationException("Not yet implemented."); } public boolean isSigned(int column) throws SQLException { return false; } public boolean isWritable(int column) throws SQLException { throw new UnsupportedOperationException("Not yet implemented."); } public static class ColSpec { public final String name; public final DBType type; public final int width; public final int precision; public final int scale; public final boolean nullable; public ColSpec(String name) { this.name = name; this.type = DBType.OBJECT; this.width = 0; this.precision = 0; this.scale = 0; this.nullable = true; } public ColSpec(String name, boolean nullable) { this.name = name; this.type = DBType.OBJECT; this.width = 0; this.precision = 0; this.scale = 0; this.nullable = nullable; } public ColSpec(String name, DBType type) { this.name = name; this.type = type; this.width = 0; this.precision = 0; this.scale = 0; this.nullable = true; } public ColSpec(String name, DBType type, boolean nullable) { this.name = name; this.type = type; this.width = 0; this.precision = 0; this.scale = 0; this.nullable = nullable; } public ColSpec(String name, DBType type, int width) { this.name = name; this.type = type; this.width = width; this.precision = 0; this.scale = 0; this.nullable = true; } public ColSpec(String name, DBType type, int precision, int scale) { this.name = name; this.type = type; this.precision = precision; this.scale = scale; this.width = 0; this.nullable = true; } public ColSpec(String name, DBType type, int width, boolean nullable) { this.name = name; this.type = type; this.width = width; this.precision = 0; this.scale = 0; this.nullable = nullable; } public ColSpec(String name, DBType type, int precision, int scale, boolean nullable) { this.name = name; this.type = type; this.precision = precision; this.scale = scale; this.width = 0; this.nullable = nullable; } } public enum DBTypeGroup { Time(0), Number(1), String(2), Complex(3), Other(4); public int value; private DBTypeGroup(int i) { value = i; } } public enum DBType { BLOB(byte[].class,Types.BLOB,DBTypeGroup.Other), BIT(boolean.class,Types.BIT,DBTypeGroup.Number), CHAR(char.class,Types.CHAR,DBTypeGroup.Number), DECIMAL(BigDecimal.class,Types.DECIMAL,DBTypeGroup.Number), FLOAT(float.class,Types.FLOAT,DBTypeGroup.Number), DOUBLE(double.class,Types.DOUBLE,DBTypeGroup.Number), SHORT(short.class,Types.SMALLINT,DBTypeGroup.Number), INTEGER(int.class,Types.INTEGER,DBTypeGroup.Number), LONG(long.class,Types.BIGINT,DBTypeGroup.Number), BYTE(byte.class,Types.TINYINT,DBTypeGroup.Number), STRING(String.class,Types.VARCHAR,DBTypeGroup.String), TIMESTAMP(Timestamp.class,Types.TIMESTAMP,DBTypeGroup.Time), OBJECT(Object.class,Types.JAVA_OBJECT,DBTypeGroup.Complex); public final Class javaClass; public final int sqltype; public final DBTypeGroup group; private DBType(Class javaClass, int sqltype, DBTypeGroup group) { this.javaClass = javaClass; this.sqltype = sqltype; this.group = group; } public static DBType valueOf(int sqlType) { switch (sqlType) { case Types.BLOB: case Types.CLOB: case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY: return DBType.BLOB; case Types.BIGINT: return DBType.LONG; case Types.BOOLEAN: case Types.BIT: return DBType.BIT; case Types.CHAR: return DBType.CHAR; case Types.DOUBLE: return DBType.DOUBLE; case Types.FLOAT: return DBType.FLOAT; case Types.INTEGER: return DBType.INTEGER; case Types.SMALLINT: return DBType.SHORT; case Types.TINYINT: return DBType.BYTE; case Types.NUMERIC: case Types.REAL: case Types.DECIMAL: return DBType.DECIMAL; case Types.VARCHAR: case Types.LONGVARCHAR: return DBType.STRING; case Types.DATE: case Types.TIME: case Types.TIMESTAMP: return DBType.TIMESTAMP; case Types.JAVA_OBJECT: case Types.ARRAY: case Types.STRUCT: return DBType.OBJECT; case Types.REF: case Types.DISTINCT: case Types.NULL: case Types.OTHER: case Types.DATALINK: default: throw new IllegalArgumentException("Unsupported JDBC type"); } } } @Override public T unwrap(Class iface) throws SQLException { // TODO Auto-generated method stub return null; } @Override public boolean isWrapperFor(Class iface) throws SQLException { // TODO Auto-generated method stub return false; } }