// Path: mongodb/src/main/java/eu/drus/jpa/unit/mongodb/ext/ConfigurationRegistry.java
// public class ConfigurationRegistry {
// 
//     private static final ServiceLoader<ConfigurationFactory> CONFIG_FACTORIES = ServiceLoader.load(ConfigurationFactory.class);
// 
//     public boolean hasConfiguration(final PersistenceUnitDescriptor descriptor) {
//         for (final ConfigurationFactory factory : CONFIG_FACTORIES) {
//             if (factory.isSupported(descriptor)) {
//                 return true;
//             }
//         }
//         return false;
//     }
// 
//     public Configuration getConfiguration(final PersistenceUnitDescriptor descriptor) {
//         for (final ConfigurationFactory factory : CONFIG_FACTORIES) {
//             if (factory.isSupported(descriptor)) {
//                 return factory.createConfiguration(descriptor);
//             }
//         }
//         throw new JpaUnitException("Unsupported JPA provider");
//     }
// }
// 
// Path: core/src/main/java/eu/drus/jpa/unit/spi/ExecutionContext.java
// public interface ExecutionContext {
// 
//     Field getPersistenceField();
// 
//     PersistenceUnitDescriptor getDescriptor();
// 
//     void storeData(String key, Object value);
// 
//     Object getData(String key);
// }
// 
// Path: core/src/main/java/eu/drus/jpa/unit/spi/TestInvocation.java
// public interface TestInvocation {
// 
//     Class<?> getTestClass();
// 
//     ExecutionContext getContext();
// 
//     Optional<Method> getTestMethod();
// 
//     Optional<Object> getTestInstance();
// 
//     Optional<Throwable> getException();
// 
//     FeatureResolver getFeatureResolver();
// }
// 
// Path: core/src/main/java/eu/drus/jpa/unit/spi/TestMethodDecorator.java
// public interface TestMethodDecorator extends TestDecorator {
// 
//     boolean isConfigurationSupported(ExecutionContext ctx);
// 
//     void beforeTest(TestInvocation invocation) throws Exception;
// 
//     void afterTest(TestInvocation invocation) throws Exception;
// }


import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
import eu.drus.jpa.unit.mongodb.ext.Configuration;
import eu.drus.jpa.unit.mongodb.ext.ConfigurationRegistry;
import eu.drus.jpa.unit.spi.ExecutionContext;
import eu.drus.jpa.unit.spi.TestInvocation;
import eu.drus.jpa.unit.spi.TestMethodDecorator;
package eu.drus.jpa.unit.mongodb;



public class MongoDbDecorator implements TestMethodDecorator {

    private ConfigurationRegistry configurationRegistry = new ConfigurationRegistry();

    @Override
    public int getPriority() {
        return 3;
    }

    @Override
    public void beforeTest(final TestInvocation invocation) throws Exception {
        final ExecutionContext context = invocation.getContext();

        final Configuration configuration = configurationRegistry.getConfiguration(context.getDescriptor());

        final MongoClient client = (MongoClient) context.getData(Constants.KEY_MONGO_CLIENT);
        final MongoDatabase mongoDb = client.getDatabase(configuration.getDatabaseName());
        context.storeData(Constants.KEY_MONGO_DB, mongoDb);

        final MongoDbFeatureExecutor dbFeatureExecutor = new MongoDbFeatureExecutor(invocation.getFeatureResolver());

        dbFeatureExecutor.executeBeforeTest(mongoDb);
        context.storeData(Constants.KEY_FEATURE_EXECUTOR, dbFeatureExecutor);
    }

    @Override
    public void afterTest(final TestInvocation invocation) throws Exception {
        final ExecutionContext context = invocation.getContext();

        final MongoDatabase mongoDb = (MongoDatabase) context.getData(Constants.KEY_MONGO_DB);
        final MongoDbFeatureExecutor dbFeatureExecutor = (MongoDbFeatureExecutor) context.getData(Constants.KEY_FEATURE_EXECUTOR);
        context.storeData(Constants.KEY_MONGO_DB, null);
        context.storeData(Constants.KEY_FEATURE_EXECUTOR, null);

        dbFeatureExecutor.executeAfterTest(mongoDb, invocation.getException().isPresent());
    }

    @Override
// Path: mongodb/src/main/java/eu/drus/jpa/unit/mongodb/ext/ConfigurationRegistry.java
// public class ConfigurationRegistry {
// 
//     private static final ServiceLoader<ConfigurationFactory> CONFIG_FACTORIES = ServiceLoader.load(ConfigurationFactory.class);
// 
//     public boolean hasConfiguration(final PersistenceUnitDescriptor descriptor) {
//         for (final ConfigurationFactory factory : CONFIG_FACTORIES) {
//             if (factory.isSupported(descriptor)) {
//                 return true;
//             }
//         }
//         return false;
//     }
// 
//     public Configuration getConfiguration(final PersistenceUnitDescriptor descriptor) {
//         for (final ConfigurationFactory factory : CONFIG_FACTORIES) {
//             if (factory.isSupported(descriptor)) {
//                 return factory.createConfiguration(descriptor);
//             }
//         }
//         throw new JpaUnitException("Unsupported JPA provider");
//     }
// }
// 
// Path: core/src/main/java/eu/drus/jpa/unit/spi/ExecutionContext.java
// public interface ExecutionContext {
// 
//     Field getPersistenceField();
// 
//     PersistenceUnitDescriptor getDescriptor();
// 
//     void storeData(String key, Object value);
// 
//     Object getData(String key);
// }
// 
// Path: core/src/main/java/eu/drus/jpa/unit/spi/TestInvocation.java
// public interface TestInvocation {
// 
//     Class<?> getTestClass();
// 
//     ExecutionContext getContext();
// 
//     Optional<Method> getTestMethod();
// 
//     Optional<Object> getTestInstance();
// 
//     Optional<Throwable> getException();
// 
//     FeatureResolver getFeatureResolver();
// }
// 
// Path: core/src/main/java/eu/drus/jpa/unit/spi/TestMethodDecorator.java
// public interface TestMethodDecorator extends TestDecorator {
// 
//     boolean isConfigurationSupported(ExecutionContext ctx);
// 
//     void beforeTest(TestInvocation invocation) throws Exception;
// 
//     void afterTest(TestInvocation invocation) throws Exception;
// }


// Path: mongodb/src/main/java/eu/drus/jpa/unit/mongodb/MongoDbDecorator.java
import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
import eu.drus.jpa.unit.mongodb.ext.Configuration;
import eu.drus.jpa.unit.mongodb.ext.ConfigurationRegistry;
import eu.drus.jpa.unit.spi.ExecutionContext;
import eu.drus.jpa.unit.spi.TestInvocation;
import eu.drus.jpa.unit.spi.TestMethodDecorator;

package eu.drus.jpa.unit.mongodb;



public class MongoDbDecorator implements TestMethodDecorator {

    private ConfigurationRegistry configurationRegistry = new ConfigurationRegistry();

    @Override
    public int getPriority() {
        return 3;
    }

    @Override
    public void beforeTest(final TestInvocation invocation) throws Exception {
        final ExecutionContext context = invocation.getContext();

        final Configuration configuration = configurationRegistry.getConfiguration(context.getDescriptor());

        final MongoClient client = (MongoClient) context.getData(Constants.KEY_MONGO_CLIENT);
        final MongoDatabase mongoDb = client.getDatabase(configuration.getDatabaseName());
        context.storeData(Constants.KEY_MONGO_DB, mongoDb);

        final MongoDbFeatureExecutor dbFeatureExecutor = new MongoDbFeatureExecutor(invocation.getFeatureResolver());

        dbFeatureExecutor.executeBeforeTest(mongoDb);
        context.storeData(Constants.KEY_FEATURE_EXECUTOR, dbFeatureExecutor);
    }

    @Override
    public void afterTest(final TestInvocation invocation) throws Exception {
        final ExecutionContext context = invocation.getContext();

        final MongoDatabase mongoDb = (MongoDatabase) context.getData(Constants.KEY_MONGO_DB);
        final MongoDbFeatureExecutor dbFeatureExecutor = (MongoDbFeatureExecutor) context.getData(Constants.KEY_FEATURE_EXECUTOR);
        context.storeData(Constants.KEY_MONGO_DB, null);
        context.storeData(Constants.KEY_FEATURE_EXECUTOR, null);

        dbFeatureExecutor.executeAfterTest(mongoDb, invocation.getException().isPresent());
    }

    @Override
    public boolean isConfigurationSupported(final ExecutionContext ctx) {