package org.needle4j.db;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import org.needle4j.configuration.NeedleConfiguration;
import org.needle4j.configuration.PropertyBasedConfigurationFactory;
import org.needle4j.db.operation.DBOperation;
import org.needle4j.db.transaction.TransactionHelper;
import org.needle4j.injection.InjectionProvider;
import org.needle4j.injection.InjectionTargetInformation;
/**
* Base class for a database test case. Executes optional database operation on
* test setup and tear down.
*
* May be used as an injection provider for {@link EntityManager},
* {@link EntityManagerFactory} and {@link EntityTransaction}.
*
* @see InjectionProvider
* @see DBOperation
*
*/
public class DatabaseTestcase implements InjectionProvider<Object> {
private final DatabaseTestcaseConfiguration configuration;
private TransactionHelper transactionHelper;
private DBOperation dbOperation;
private Map<Class<?>, InjectionProvider<?>> injectionProviderMap = new HashMap<Class<?>, InjectionProvider<?>>();
{
injectionProviderMap.put(EntityManager.class, new EntityManagerProvider(this));
injectionProviderMap.put(EntityManagerFactory.class, new EntityManagerFactoryProvider(this));
injectionProviderMap.put(EntityTransaction.class, new EntityTransactionProvider(this));
injectionProviderMap.put(TransactionHelper.class, new TransactionHelperProvider(this));
}
/**
* Creates an instance of {@link DatabaseTestcase} with the global
* configured persistence unit name and the global configured
* {@link DBOperation}.
*
* @see DBOperation
*/
public DatabaseTestcase() {
configuration = new DatabaseTestcaseConfiguration(PropertyBasedConfigurationFactory.get());
}
/**
* Creates an instance of {@link DatabaseTestcase} with the global
* configured persistence unit name and overrides the global configured
* {@link DBOperation} with the given database operation.
*
* @param dbOperation
* database operation to execute on test setup and tear down
*
* @see DBOperation
*/
public DatabaseTestcase(final DBOperation dbOperation) {
this();
this.dbOperation = dbOperation;
}
/**
* Creates an instance of {@link DatabaseTestcase} with the given
* persistence unit name and the global configured {@link DBOperation}.
*
* @param persistenceUnitName
* the name of the persistence unit
*
* @see DBOperation
*/
public DatabaseTestcase(final String persistenceUnitName) {
configuration = new DatabaseTestcaseConfiguration(PropertyBasedConfigurationFactory.get(), persistenceUnitName);
}
/**
* Creates an instance of {@link DatabaseTestcase} with the given
* persistence unit name and overrides the global configured
* {@link DBOperation} with the given database operation.
*
* @param persistenceUnitName
* the name of the persistence unit
* @param dbOperation
* database operation to execute on test setup and tear down
*
* @see DBOperation
*/
public DatabaseTestcase(final String persistenceUnitName, final DBOperation dbOperation) {
this(persistenceUnitName);
this.dbOperation = dbOperation;
}
/**
* Creates an instance of {@link DatabaseTestcase} for the given entity
* classes by using the configured hibernate specific configuration file
* (*cfg.xml) and use the global configured {@link DBOperation}.
*
* @param clazzes
* the entity classes
* @see DBOperation
*
*/
@Deprecated
public DatabaseTestcase(final Class<?>... clazzes) {
configuration = new DatabaseTestcaseConfiguration(PropertyBasedConfigurationFactory.get(), clazzes);
}
/**
* Creates an instance of {@link DatabaseTestcase} for the given entity
* classes by using the configured hibernate specific configuration file
* (*cfg.xml) and overrides the global configured {@link DBOperation} with
* the give database operation.
*
* @param dbOperation
* database operation to execute on test setup and tear down
* @param clazzes
* the entity classes
*
* @see DBOperation
*/
@Deprecated
public DatabaseTestcase(final DBOperation dbOperation, final Class<?>... clazzes) {
this(clazzes);
this.dbOperation = dbOperation;
}
protected DatabaseTestcase(final NeedleConfiguration needleConfiguration) {
configuration = new DatabaseTestcaseConfiguration(needleConfiguration,
needleConfiguration.getPersistenceunitName());
}
/**
* Execute tear down database operation, if configured.
*
* @throws Exception
* thrown if an error occurs
*/
protected void after() throws Exception {
final DBOperation operation = getDBOperation();
if (operation != null) {
operation.tearDownOperation();
}
getEntityManager().clear();
}
/**
* Execute setup database operation, if configured.
*
* @throws Exception
* thrown if an error occurs
*/
protected void before() throws Exception {
final DBOperation operation = getDBOperation();
if (operation != null) {
operation.setUpOperation();
}
}
private DBOperation getDBOperation() {
return dbOperation != null ? dbOperation : configuration.getDBOperation();
}
/**
* Returns the {@link EntityManager}.
*
* @return {@link EntityManager}.
*/
public EntityManager getEntityManager() {
return configuration.getEntityManager();
}
/**
* Returns the {@link EntityManagerFactory}.
*
* @return {@link EntityManagerFactory}.
*/
public EntityManagerFactory getEntityManagerFactory() {
return configuration.getEntityManagerFactory();
}
/**
* Returns an instance of {@link TransactionHelper}
*
* @see TransactionHelper
* @return {@link TransactionHelper}
*/
public TransactionHelper getTransactionHelper() {
if (transactionHelper == null) {
transactionHelper = new TransactionHelper(getEntityManager());
}
return transactionHelper;
}
@Override
public Object getInjectedObject(final Class<?> injectionPointType) {
return getInjectionProvider(injectionPointType).getInjectedObject(injectionPointType);
}
@Override
public boolean verify(final InjectionTargetInformation injectionTargetInformation) {
final InjectionProvider<?> injectionProvider = getInjectionProvider(injectionTargetInformation.getType());
return injectionProvider != null && injectionProvider.verify(injectionTargetInformation);
}
@Override
public Object getKey(final InjectionTargetInformation injectionTargetInformation) {
return getInjectionProvider(injectionTargetInformation.getType()).getKey(injectionTargetInformation);
}
private InjectionProvider<?> getInjectionProvider(final Class<?> type) {
return injectionProviderMap.get(type);
}
}