/*
* 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;
}
}