package com.buschmais.xo.test;
import static com.buschmais.xo.api.Query.Result;
import static com.buschmais.xo.api.Query.Result.CompositeRowObject;
import java.net.URI;
import java.util.*;
import org.junit.After;
import org.junit.Before;
import com.buschmais.xo.api.*;
import com.buschmais.xo.api.bootstrap.XO;
import com.buschmais.xo.api.bootstrap.XOUnit;
/**
* Abstract base class for parametrized XO tests.
*/
public abstract class AbstractXOManagerTest {
/**
* Defines a database under test. Intended to be implemented by enum types.
*/
public interface Database {
URI getUri();
Class<?> getProvider();
Properties getProperties();
}
private XOUnit xoUnit;
private XOManagerFactory xoManagerFactory;
private XOManager xoManager = null;
/**
* Return a collection of {@link com.buschmais.xo.api.bootstrap.XOUnit}s
* initialized with the given parameters.
*
* @param databases
* The databases to use.
* @param types
* The types to register.
* @return The collection of {@link com.buschmais.xo.api.bootstrap.XOUnit}s.
*/
protected static Collection<Object[]> xoUnits(List<? extends Database> databases, List<? extends Class<?>> types) {
return xoUnits(databases, types, Collections.<Class<?>> emptyList(), ValidationMode.AUTO, ConcurrencyMode.SINGLETHREADED,
Transaction.TransactionAttribute.NONE);
}
/**
* Return a collection of {@link com.buschmais.xo.api.bootstrap.XOUnit}s
* initialized with the given parameters.
*
* @param databases
* The databases to use.
* @param types
* The types to register.
* @param instanceListenerTypes
* The instance listeners to register.
* @param validationMode
* The validation mode to use.
* @param concurrencyMode
* The concurrency mode to use.
* @param transactionAttribute
* The transaction attribute to use.
* @return The collection of {@link com.buschmais.xo.api.bootstrap.XOUnit}s.
*/
protected static Collection<Object[]> xoUnits(List<? extends Database> databases, List<? extends Class<?>> types,
List<? extends Class<?>> instanceListenerTypes, ValidationMode validationMode, ConcurrencyMode concurrencyMode,
Transaction.TransactionAttribute transactionAttribute) {
List<Object[]> xoUnits = new ArrayList<>(databases.size());
for (Database database : databases) {
XOUnit unit = xoUnit(database, types, instanceListenerTypes, validationMode, concurrencyMode, transactionAttribute);
xoUnits.add(new Object[] { unit });
}
return xoUnits;
}
/**
* Return a {@link com.buschmais.xo.api.bootstrap.XOUnit} initialized with
* the given parameters.
*
* @param types
* The types to register.
* @return The {@link com.buschmais.xo.api.bootstrap.XOUnit}.
*/
protected static XOUnit xoUnit(Database database, List<? extends Class<?>> types) {
return xoUnit(database, types, Collections.<Class<?>> emptyList(), ValidationMode.AUTO, ConcurrencyMode.SINGLETHREADED,
Transaction.TransactionAttribute.NONE);
}
/**
* Return a {@link com.buschmais.xo.api.bootstrap.XOUnit} initialized with
* the given parameters.
*
* @param types
* The types to register.
* @param instanceListenerTypes
* The instance listeners to register.
* @param validationMode
* The validation mode to use.
* @param concurrencyMode
* The concurrency mode to use.
* @param transactionAttribute
* The transaction attribute to use.
* @return The {@link com.buschmais.xo.api.bootstrap.XOUnit}.
*/
protected static XOUnit xoUnit(Database database, List<? extends Class<?>> types, List<? extends Class<?>> instanceListenerTypes,
ValidationMode validationMode, ConcurrencyMode concurrencyMode, Transaction.TransactionAttribute transactionAttribute) {
return XOUnit.builder().name("default").description("Default XO unit").uri(database.getUri()).provider(database.getProvider())
.types(new HashSet<>(types)).instanceListeners(instanceListenerTypes).validationMode(validationMode).concurrencyMode(concurrencyMode)
.defaultTransactionAttribute(transactionAttribute).properties(database.getProperties()).build();
}
/**
* Parametrized constructor.
*
* @param xoUnit
* The {@link com.buschmais.xo.api.bootstrap.XOUnit} to use.
*/
protected AbstractXOManagerTest(XOUnit xoUnit) {
this.xoUnit = xoUnit;
}
/**
* Creates the {@link com.buschmais.xo.api.XOManagerFactory}.
*/
@Before
public void createXOManagerFactory() {
xoManagerFactory = XO.createXOManagerFactory(xoUnit);
dropDatabase();
}
/**
* Closes the {@link com.buschmais.xo.api.XOManagerFactory}.
*/
@After
public void closeXOManagerFactory() {
closeXOmanager();
if (xoManagerFactory != null) {
xoManagerFactory.close();
}
}
/**
* Executes a createQuery and returns a {@link TestResult}.
*
* @param query
* The createQuery.
* @return The {@link TestResult}.
*/
protected TestResult executeQuery(String query) {
return executeQuery(query, Collections.<String, Object> emptyMap());
}
/**
* Executes a query and returns a {@link TestResult}.
*
* @param query
* The query.
* @param parameters
* The parameters.
* @return The {@link TestResult}.
*/
protected TestResult executeQuery(String query, Map<String, Object> parameters) {
Result<CompositeRowObject> result = xoManager.createQuery(query).withParameters(parameters).execute();
Map<String, List<Object>> columns = new HashMap<>();
for (CompositeRowObject row : result) {
Iterable<String> columnNames = row.getColumns();
for (String columnName : columnNames) {
List<Object> columnValues = columns.get(columnName);
if (columnValues == null) {
columnValues = new ArrayList<>();
columns.put(columnName, columnValues);
}
columnValues.add(row.get(columnName, Object.class));
}
}
return new TestResult(columns);
}
/**
* Return the {@link com.buschmais.xo.api.XOManagerFactory}.
*
* @return The {@link com.buschmais.xo.api.XOManagerFactory}.
*/
protected XOManagerFactory getXOManagerFactory() {
return xoManagerFactory;
}
@Deprecated
protected XOManagerFactory getXoManagerFactory() {
return getXOManagerFactory();
}
/**
* Return the current {@link com.buschmais.xo.api.XOManager}.
*
* @return The current {@link com.buschmais.xo.api.XOManager}.
*/
protected XOManager getXOManager() {
if (xoManager == null) {
xoManager = getXoManagerFactory().createXOManager();
}
return xoManager;
}
@Deprecated
protected XOManager getXoManager() {
return getXOManager();
}
/**
* Close the current {@link com.buschmais.xo.api.XOManager}.
*/
protected void closeXOmanager() {
if (xoManager != null) {
XOTransaction transaction = xoManager.currentTransaction();
if (transaction != null && transaction.isActive()) {
transaction.rollback();
}
xoManager.close();
xoManager = null;
}
}
/**
* Represents a test result which allows fetching values by row or columns.
*/
protected class TestResult {
private Map<String, List<Object>> columns;
TestResult(Map<String, List<Object>> columns) {
this.columns = columns;
}
/**
* Return a column identified by its name.
*
* @param <T>
* The expected type.
* @return All columns.
*/
public <T> List<T> getColumn(String name) {
return (List<T>) columns.get(name);
}
}
/**
* Drop all data from the database.
*/
protected abstract void dropDatabase();
}