
org.dbunit.dataset.AbstractTableMetaData Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jtidy Show documentation
Show all versions of jtidy Show documentation
old 2002 version of xmlc-jtidy
The newest version!
/*
*
* The DbUnit Database Testing Framework
* Copyright (C)2002-2004, DbUnit.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package org.dbunit.dataset;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.dbunit.DatabaseUnitRuntimeException;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.datatype.IDataTypeFactory;
import org.dbunit.dataset.datatype.IDbProductRelatable;
import org.dbunit.dataset.filter.IColumnFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Manuel Laflamme
* @author Last changed by: $Author$
* @version $Revision$ $Date$
* @since 1.0 (Mar 8, 2002)
*/
public abstract class AbstractTableMetaData implements ITableMetaData
{
private Map _columnsToIndexes;
/**
* Logger for this class
*/
private static final Logger logger = LoggerFactory.getLogger(AbstractTableMetaData.class);
/**
* Default constructor
*/
public AbstractTableMetaData()
{
}
/**
* @param columns
* @param keyNames
* @return The primary key columns
* @deprecated since 2.3.0 - use {@link Columns#getColumns(String[], Column[])}
*/
protected static Column[] getPrimaryKeys(Column[] columns, String[] keyNames)
{
logger.debug("getPrimaryKeys(columns={}, keyNames={}) - start", columns, keyNames);
return Columns.getColumns(keyNames, columns);
}
/**
* @param tableName
* @param columns
* @param columnFilter
* @return The filtered primary key columns
* @deprecated since 2.3.0 - use {@link Columns#getColumns(String[], Column[])}
*/
protected static Column[] getPrimaryKeys(String tableName, Column[] columns,
IColumnFilter columnFilter)
{
if (logger.isDebugEnabled())
{
logger.debug("getPrimaryKeys(tableName={}, columns={}, columnFilter={}) - start",
new Object[]{ tableName, columns, columnFilter });
}
return Columns.getColumns(tableName, columns, columnFilter);
}
/**
* Provides the index of the column with the given name within this table.
* Uses method {@link ITableMetaData#getColumns()} to retrieve all available columns.
* @throws DataSetException
* @see org.dbunit.dataset.ITableMetaData#getColumnIndex(java.lang.String)
*/
public int getColumnIndex(String columnName) throws DataSetException
{
logger.debug("getColumnIndex(columnName={}) - start", columnName);
if(this._columnsToIndexes == null)
{
// lazily create the map
this._columnsToIndexes = createColumnIndexesMap(this.getColumns());
}
String columnNameUpperCase = columnName.toUpperCase();
Integer colIndex = (Integer) this._columnsToIndexes.get(columnNameUpperCase);
if(colIndex != null)
{
return colIndex.intValue();
}
else
{
throw new NoSuchColumnException(this.getTableName(), columnNameUpperCase,
" (Non-uppercase input column: "+columnName+") in ColumnNameToIndexes cache map. " +
"Note that the map's column names are NOT case sensitive.");
}
}
/**
* @param columns The columns to be put into the hash table
* @return A map having the key value pair [columnName, columnIndexInInputArray]
*/
private Map createColumnIndexesMap(Column[] columns)
{
Map colsToIndexes = new HashMap(columns.length);
for (int i = 0; i < columns.length; i++)
{
colsToIndexes.put(columns[i].getColumnName().toUpperCase(), new Integer(i));
}
return colsToIndexes;
}
/**
* Validates and returns the datatype factory of the given connection
* @param connection The connection providing the {@link IDataTypeFactory}
* @return The datatype factory of the given connection
* @throws SQLException
*/
public IDataTypeFactory getDataTypeFactory(IDatabaseConnection connection)
throws SQLException
{
DatabaseConfig config = connection.getConfig();
Object factoryObj = config.getProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY);
if(!IDataTypeFactory.class.isAssignableFrom(factoryObj.getClass())) {
String msg = "Invalid datatype factory configured. Class '" +
factoryObj.getClass() + "' does not implement '" + IDataTypeFactory.class + "'.";
if(factoryObj instanceof String){
msg += " Ensure not to specify the fully qualified class name as String but the concrete " +
"instance of the datatype factory (for example 'new OracleDataTypeFactory()').";
}
// TODO Would a "DatabaseUnitConfigurationException make more sense?
throw new DatabaseUnitRuntimeException(msg);
}
IDataTypeFactory dataTypeFactory = (IDataTypeFactory)factoryObj;
// Validate, e.g. oracle metaData + oracleDataTypeFactory ==> OK
Connection jdbcConnection = connection.getConnection();
DatabaseMetaData metaData = jdbcConnection.getMetaData();
String validationMessage = validateDataTypeFactory(dataTypeFactory, metaData);
if(validationMessage!=null){
// Inform the user that we think he could get trouble with the current configuration
logger.warn("Potential problem found: " + validationMessage);
}
return dataTypeFactory;
}
/**
* Verifies that the data type factory supports the database product on the connection.
* If the data type factory is not valid for the connection, a warning is logged.
* @param dataTypeFactory The data type factory to validate.
* @param metaData The {@link DatabaseMetaData} needed to get the DB product name of the connection RDBMS.
* @return A validation message if there is a potential problem or null
if everything is fine.
* @throws java.sql.SQLException A database problem.
*/
String validateDataTypeFactory(IDataTypeFactory dataTypeFactory, DatabaseMetaData metaData)
throws SQLException
{
if (!(dataTypeFactory instanceof IDbProductRelatable))
{
return null;
}
IDbProductRelatable productRelatable = (IDbProductRelatable) dataTypeFactory;
String databaseProductName = metaData.getDatabaseProductName();
Collection validDbProductCollection = productRelatable.getValidDbProducts();
if (validDbProductCollection != null)
{
String lowerCaseDbProductName = databaseProductName.toLowerCase();
for (Iterator iterator = validDbProductCollection.iterator(); iterator.hasNext();) {
String validDbProduct = ((String) iterator.next()).toLowerCase();
if(lowerCaseDbProductName.indexOf(validDbProduct) > -1) {
logger.debug("The current database '{}' fits to the configured data type factory '{}'. Validation successful.",
databaseProductName, dataTypeFactory);
return null;
}
}
}
// If we get here, the validation failed
String validationMessage = "The configured data type factory '" + dataTypeFactory.getClass() +
"' might cause problems with the current database '" + databaseProductName +
"' (e.g. some datatypes may not be supported properly). " +
"In rare cases you might see this message because the list of supported database " +
"products is incomplete (list=" + validDbProductCollection + "). " +
"If so please request a java-class update via the forums." +
"If you are using your own IDataTypeFactory extending " +
"DefaultDataTypeFactory, ensure that you override getValidDbProducts() " +
"to specify the supported database products.";
return validationMessage;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy