package de.ppi.samples.fuwesta.dbunit; import java.sql.Connection; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import org.dbunit.Assertion; import org.dbunit.IDatabaseTester; import org.dbunit.database.DatabaseConfig; import org.dbunit.dataset.Column; import org.dbunit.dataset.FilteredDataSet; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.ITable; import org.dbunit.dataset.ITableIterator; import org.dbunit.dataset.SortedTable; import org.dbunit.dataset.filter.IColumnFilter; import org.dbunit.ext.mssql.InsertIdentityOperation; import org.dbunit.operation.DatabaseOperation; import org.dbunit.validator.ValidatorFailureHandler; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; import de.ppi.samples.fuwesta.dbunit.rowbuilder.PostRowBuilder; import de.ppi.samples.fuwesta.dbunit.rowbuilder.TUserRowBuilder; import de.ppi.samples.fuwesta.dbunit.rowbuilder.TagPostingsRowBuilder; import de.ppi.samples.fuwesta.dbunit.rowbuilder.TagRowBuilder; /** * * Rule to get access to the database. * */ public class FuWeStaSampleDatabase implements TestRule { /** * Batchsize for SQL-Statements. */ private static final Integer BATCH_SIZE = Integer.valueOf(100); /** * The database-connection. */ private final Connection connection; /** * The database schema. */ private final String schema; /** * DBUnit- Class to test the database connection. */ private static IDatabaseTester databaseTester = null; /** * Dataset of tables which should be delete. */ private static IDataSet deleteDataSet = null; /** * Map a table-name to a unique-key. */ private static Map<String, String[]> tableToUniqueKey = new HashMap<>(); /** * Map a table-name to a primary-key. */ private static Map<String, String[]> tableToPrimaryKey = new HashMap<>(); static { tableToPrimaryKey.put(PostRowBuilder.TABLE_NAME, PostRowBuilder.PRIMARY_KEY); tableToPrimaryKey.put(TUserRowBuilder.TABLE_NAME, TUserRowBuilder.PRIMARY_KEY); tableToPrimaryKey.put(TagRowBuilder.TABLE_NAME, TagRowBuilder.PRIMARY_KEY); tableToPrimaryKey.put(PostRowBuilder.TABLE_NAME, PostRowBuilder.PRIMARY_KEY); tableToPrimaryKey.put(TagPostingsRowBuilder.TABLE_NAME, TagPostingsRowBuilder.ALL_COLUMNS); tableToUniqueKey.putAll(tableToPrimaryKey); tableToUniqueKey.put(TUserRowBuilder.TABLE_NAME, new String[] { TUserRowBuilder.C_USER_ID }); tableToUniqueKey.put(TagRowBuilder.TABLE_NAME, new String[] { TagRowBuilder.C_NAME }); } /** * Initiates an object of type {@link FuWeStaSampleDatabase}. * * @param connection the database connection. * @param schema the database schema. */ public FuWeStaSampleDatabase(Connection connection, String schema) { super(); this.connection = connection; this.schema = schema; } /** * Initialisiert DBUnit. * * @throws Exception wenn was schief geht. */ public void initDatabase() throws Exception { if (databaseTester == null) { databaseTester = new GenericDatabaseTester(connection, schema); setUpDatabaseConfig(databaseTester.getConnection().getConfig()); } if (deleteDataSet == null) { deleteDataSet = new FuWeStaSampleDataSet(databaseTester.getConnection() .createDataSet()); } } /** * Print all tablenames of the database. */ void printTableNames() { try { FuWeStaSampleDataSet .printTableNames(databaseTester.getConnection()); } catch (Exception e) { throw new IllegalStateException("error getting connection", e); } } /** * Configure database. * * @param config the database-config. */ private void setUpDatabaseConfig(DatabaseConfig config) { config.setProperty(DatabaseConfig.PROPERTY_BATCH_SIZE, BATCH_SIZE); config.setProperty(DatabaseConfig.FEATURE_BATCHED_STATEMENTS, Boolean.TRUE); config.setProperty(DatabaseConfig.PROPERTY_PRIMARY_KEY_FILTER, new IColumnFilter() { @Override public boolean accept(String tableName, Column column) { if (tableToPrimaryKey.containsKey(tableName)) { return Arrays.asList( tableToPrimaryKey.get(tableName)).contains( column.getColumnName()); } else { return column.getColumnName() .equalsIgnoreCase("id"); } } }); } /** * Call db-unit about the end of the test. */ public void tearDownDb() { try { databaseTester.onTearDown(); } catch (Exception e) { throw new IllegalStateException("Error tearDownDb", e); } } /** * Shutdown the database. * */ public static void destroyDatabase() { try { deleteDataSet = null; databaseTester = null; } catch (Exception e) { throw new IllegalStateException("Error during database shutdown", e); } } /** * Delete all data first and insert the dataset. * * @param dataSet the set with data. */ public void cleanlyInsert(IDataSet dataSet) { try { InsertIdentityOperation.DELETE.execute( databaseTester.getConnection(), deleteDataSet); databaseTester.setSetUpOperation(DatabaseOperation.INSERT); databaseTester.setDataSet(new FuWeStaSampleDataSet(dataSet)); databaseTester.onSetup(); } catch (Exception e) { throw new IllegalStateException("Error during clean-insert", e); } } /** * Delete all data. * */ public void clean() { try { InsertIdentityOperation.DELETE.execute( databaseTester.getConnection(), deleteDataSet); } catch (Exception e) { throw new IllegalStateException("Error during clean", e); } } /** * Check if the content of the database as expected. * * @param expected the expected dataset. */ public void checkResult(final IDataSet expected) { try { final IDataSet actual = databaseTester.getConnection().createDataSet(); final ITableIterator expectdTables = expected.iterator(); while (expectdTables.next()) { final String tableName = expectdTables.getTable().getTableMetaData() .getTableName(); final String[] uk = tableToUniqueKey.get(tableName); if (uk == null) { throw new IllegalStateException( "You must define a unique-key for each table."); } final ITable expectedTable = new SortedTable(expected.getTable(tableName), uk); final ITable actualTable = new SortedTable(actual.getTable(tableName), uk); Assertion.assertEquals(expectedTable, actualTable, new ValidatorFailureHandler()); } } catch (Exception e) { throw new IllegalStateException("Error during checkResult", e); } } /** * Helper method to dump the current database. * * @param fileName the file where to store. * @param tableNames the name of the tables. * @throws Exception */ public void dumpResult(String fileName, String... tableNames) { final FuWeStaSampleBuilderDataSetWriter writer = new FuWeStaSampleBuilderDataSetWriter( "de.ppi.samples.fuwesta.dbunit.dataset", fileName); try { if (tableNames != null && tableNames.length > 0) { writer.write(new FilteredDataSet(tableNames, databaseTester .getConnection().createDataSet())); } else { writer.write(deleteDataSet); } } catch (Exception e) { throw new IllegalStateException("Error during dump result", e); } } /** * Generate RowBuilder. */ void generateRowBuilder() { try { FuWeStaRowBuilderGenerator rowBuilder = new FuWeStaRowBuilderGenerator(); rowBuilder.generate(databaseTester.getConnection().createDataSet()); } catch (Exception e) { throw new IllegalStateException("Error during dump result", e); } } /** * {@inheritDoc} */ @Override public Statement apply(final Statement base, Description description) { return new Statement() { @Override public void evaluate() throws Throwable { try { initDatabase(); base.evaluate(); } finally { tearDownDb(); } } }; } }