// Path: src/main/java/com/github/arteam/jdit/maintenance/DatabaseMaintenance.java
// public interface DatabaseMaintenance {
// 
//     /**
//      * Drop all tables and sequences
//      */
//     void dropTablesAndSequences();
// 
//     /**
//      * Sweep data from the DB, but don't drop the schema.
//      * Also restart sequences, so tests can rely on their predictability.
//      */
//     void sweepData();
// }
// 
// Path: src/main/java/com/github/arteam/jdit/maintenance/DatabaseMaintenanceFactory.java
// public final class DatabaseMaintenanceFactory {
// 
//     private static final String POSTGRESQL = "PostgreSQL";
//     private static final String HSQLDB = "HSQL Database Engine";
//     private static final String H2 = "H2";
//     private static final String MYSQL = "MySQL";
// 
//     private DatabaseMaintenanceFactory() {
//     }
// 
//     public static DatabaseMaintenance create(Handle handle) {
//         String databaseVendor = getDatabaseVendor(handle);
//         switch (databaseVendor) {
//             case POSTGRESQL:
//                 return new PostgresDatabaseMaintenance(handle);
//             case HSQLDB:
//                 return new HsqlDatabaseMaintenance(handle);
//             case H2:
//                 return new H2DatabaseMaintenance(handle);
//             case MYSQL:
//                 return new MySqlDatabaseMaintenance(handle);
//             default:
//                 throw new UnsupportedOperationException(databaseVendor + " is not supported");
//         }
//     }
// 
//     private static String getDatabaseVendor(Handle handle) {
//         try {
//             return handle.getConnection().getMetaData().getDatabaseProductName();
//         } catch (SQLException e) {
//             throw new RuntimeException(e);
//         }
//     }
// }


import com.github.arteam.jdit.annotations.JditProperties;
import com.github.arteam.jdit.maintenance.DatabaseMaintenance;
import com.github.arteam.jdit.maintenance.DatabaseMaintenanceFactory;
import org.jdbi.v3.core.Handle;
import org.jdbi.v3.core.Jdbi;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
package com.github.arteam.jdit;


/**
 * <p>
 * Tests runner which:
 * <ul>
 * <li>Injects DBI related tested instances to the tests.
 * <p>Supports {@link Handle}, {@link Jdbi}, SQLObject and DBI DAO.
 * </li>
 * <li>Injects data to the DB from a script for a specific
 * method or a test</li>
 * <li>Sweeps data from the DB after every tests, so every
 * test starts with an empty schema</li>
 * </ul>
 */
public class DBIRunner extends BlockJUnit4ClassRunner {

    private DatabaseMaintenance databaseMaintenance;
    private TestObjectsInjector injector;
    private DataSetInjector dataSetInjector;
    private Class<?> klass;

    public DBIRunner(Class<?> klass) throws InitializationError {
        super(klass);
        this.klass = klass;
    }

    @Override
    protected Object createTest() throws Exception {
        Object test = super.createTest();
        // Now we can inject tested instances to the current test
        injector.injectTestedInstances(test);
        return test;
    }

    @Override
    protected Statement classBlock(RunNotifier notifier) {
        final Statement statement = super.classBlock(notifier);
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                // Open a new handle for every test
                // It affords to avoid creating a static state which makes tests more independent
                JditProperties jditProperties = klass.getAnnotation(JditProperties.class);
                Jdbi dbi = jditProperties != null ? DBIContextFactory.getDBI(jditProperties.value()) : DBIContextFactory.getDBI();
                try (Handle handle = dbi.open()) {
                    injector = new TestObjectsInjector(dbi, handle);
// Path: src/main/java/com/github/arteam/jdit/maintenance/DatabaseMaintenance.java
// public interface DatabaseMaintenance {
// 
//     /**
//      * Drop all tables and sequences
//      */
//     void dropTablesAndSequences();
// 
//     /**
//      * Sweep data from the DB, but don't drop the schema.
//      * Also restart sequences, so tests can rely on their predictability.
//      */
//     void sweepData();
// }
// 
// Path: src/main/java/com/github/arteam/jdit/maintenance/DatabaseMaintenanceFactory.java
// public final class DatabaseMaintenanceFactory {
// 
//     private static final String POSTGRESQL = "PostgreSQL";
//     private static final String HSQLDB = "HSQL Database Engine";
//     private static final String H2 = "H2";
//     private static final String MYSQL = "MySQL";
// 
//     private DatabaseMaintenanceFactory() {
//     }
// 
//     public static DatabaseMaintenance create(Handle handle) {
//         String databaseVendor = getDatabaseVendor(handle);
//         switch (databaseVendor) {
//             case POSTGRESQL:
//                 return new PostgresDatabaseMaintenance(handle);
//             case HSQLDB:
//                 return new HsqlDatabaseMaintenance(handle);
//             case H2:
//                 return new H2DatabaseMaintenance(handle);
//             case MYSQL:
//                 return new MySqlDatabaseMaintenance(handle);
//             default:
//                 throw new UnsupportedOperationException(databaseVendor + " is not supported");
//         }
//     }
// 
//     private static String getDatabaseVendor(Handle handle) {
//         try {
//             return handle.getConnection().getMetaData().getDatabaseProductName();
//         } catch (SQLException e) {
//             throw new RuntimeException(e);
//         }
//     }
// }


// Path: src/main/java/com/github/arteam/jdit/DBIRunner.java
import com.github.arteam.jdit.annotations.JditProperties;
import com.github.arteam.jdit.maintenance.DatabaseMaintenance;
import com.github.arteam.jdit.maintenance.DatabaseMaintenanceFactory;
import org.jdbi.v3.core.Handle;
import org.jdbi.v3.core.Jdbi;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;

package com.github.arteam.jdit;


/**
 * <p>
 * Tests runner which:
 * <ul>
 * <li>Injects DBI related tested instances to the tests.
 * <p>Supports {@link Handle}, {@link Jdbi}, SQLObject and DBI DAO.
 * </li>
 * <li>Injects data to the DB from a script for a specific
 * method or a test</li>
 * <li>Sweeps data from the DB after every tests, so every
 * test starts with an empty schema</li>
 * </ul>
 */
public class DBIRunner extends BlockJUnit4ClassRunner {

    private DatabaseMaintenance databaseMaintenance;
    private TestObjectsInjector injector;
    private DataSetInjector dataSetInjector;
    private Class<?> klass;

    public DBIRunner(Class<?> klass) throws InitializationError {
        super(klass);
        this.klass = klass;
    }

    @Override
    protected Object createTest() throws Exception {
        Object test = super.createTest();
        // Now we can inject tested instances to the current test
        injector.injectTestedInstances(test);
        return test;
    }

    @Override
    protected Statement classBlock(RunNotifier notifier) {
        final Statement statement = super.classBlock(notifier);
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                // Open a new handle for every test
                // It affords to avoid creating a static state which makes tests more independent
                JditProperties jditProperties = klass.getAnnotation(JditProperties.class);
                Jdbi dbi = jditProperties != null ? DBIContextFactory.getDBI(jditProperties.value()) : DBIContextFactory.getDBI();
                try (Handle handle = dbi.open()) {
                    injector = new TestObjectsInjector(dbi, handle);
                    databaseMaintenance = DatabaseMaintenanceFactory.create(handle);