py.una.pol.karaku.test.cucumber.DatabasePopulatorCucumberExecutionListener.java Source code

Java tutorial

Introduction

Here is the source code for py.una.pol.karaku.test.cucumber.DatabasePopulatorCucumberExecutionListener.java

Source

/*-
 * Copyright (c)
 *
 *       2012-2014, Facultad Politcnica, Universidad Nacional de Asuncin.
 *       2012-2014, Facultad de Ciencias Mdicas, Universidad Nacional de Asuncin.
 *       2012-2013, Centro Nacional de Computacin, Universidad Nacional de Asuncin.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301  USA
 */
package py.una.pol.karaku.test.cucumber;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import javax.validation.constraints.NotNull;
import org.hibernate.SQLQuery;
import org.hibernate.tool.hbm2ddl.SingleLineSqlCommandExtractor;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import py.una.pol.karaku.exception.KarakuRuntimeException;
import py.una.pol.karaku.test.util.DatabaseUtils;
import py.una.pol.karaku.test.util.TestUtils;
import py.una.pol.karaku.test.util.transaction.SQLFiles;
import py.una.pol.karaku.test.util.transaction.Sequences;
import py.una.pol.karaku.util.StringUtils;

/**
 * 
 * @author Rainer Reyes
 * @since 1.0
 * @version 1.0 24/10/2014
 * 
 */
public class DatabasePopulatorCucumberExecutionListener extends AbstractTestExecutionListener {

    private final String SEQUENCE_CONSTRUCTOR = "Create SEQUENCE %s;";
    private final String SEQUENCE_DESTRUCTOR = "Drop SEQUENCE %s;";

    @Override
    public void afterTestClass(TestContext testContext) throws Exception {

        super.afterTestClass(testContext);

        final Sequences sequences = AnnotationUtils.findAnnotation(testContext.getTestClass(), Sequences.class);

        if ((sequences != null) && (sequences.value() != null) && (sequences.value().length > 0)) {
            DatabaseUtils.executeDDL(SEQUENCE_DESTRUCTOR, getApplicationContext(testContext), sequences.value());
        }
    }

    /**
     * Este mtodo carga los archivos SQL tanto de la clase como del mtodo.
     * <p>
     * TODO ver la posibilidad de mover los archivos de clase a
     * {@link #beforeTestClass(TestContext)} y eliminarlos despus en
     * {@link #afterTestClass(TestContext)}
     * </p>
     * {@inheritDoc}
     * 
     * @param testContext
     *            contexto del test.
     * @throws Exception
     *             si no se encuentra el archivo se lanza una
     *             {@link IOException}
     */
    @Override
    public void beforeTestMethod(TestContext testContext) throws Exception {

        super.beforeTestMethod(testContext);

        SQLFiles sqlClassFiles = AnnotationUtils.findAnnotation(testContext.getTestMethod(), SQLFiles.class);
        executeSQLFiles(testContext, sqlClassFiles);
    }

    @Override
    public void beforeTestClass(TestContext testContext) throws Exception {

        super.beforeTestClass(testContext);

        final Sequences sequences = AnnotationUtils.findAnnotation(testContext.getTestClass(), Sequences.class);

        if ((sequences != null) && (sequences.value() != null) && (sequences.value().length > 0)) {
            DatabaseUtils.executeDDL(SEQUENCE_CONSTRUCTOR, getApplicationContext(testContext), sequences.value());
        }
        SQLFiles sqlFiles = AnnotationUtils.findAnnotation(testContext.getTestClass(), SQLFiles.class);
        executeSQLFiles(testContext, sqlFiles);
    }

    /**
     * @param testContext
     * @param sqlFiles
     */
    private void executeSQLFiles(TestContext testContext, SQLFiles sqlFiles) {

        if (sqlFiles == null) {
            return;
        }
        List<String> files = getFiles(testContext, sqlFiles);
        SingleLineSqlCommandExtractor slsce = new SingleLineSqlCommandExtractor();

        for (String file : files) {
            executeSQL(testContext, file, slsce);
        }
    }

    /**
     * @param testContext
     * @param file
     * @param slsce
     */
    private void executeSQL(TestContext testContext, String file, SingleLineSqlCommandExtractor slsce) {

        BufferedReader br;
        ClassPathResource cpr = getClassPathResource(file, testContext);
        br = _getBr(cpr);
        // File f = new File(scriptPath);
        // FileReader fr = new FileReader(file);

        final String[] commands = slsce.extractCommands(br);
        if (commands == null) {
            return;
        }
        final HibernateTransactionManager tm = getTransactionManager(testContext);
        final TransactionTemplate tt = new TransactionTemplate(tm);
        tt.execute(new TransactionCallbackWithoutResult() {

            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {

                for (String s : commands) {
                    if (StringUtils.isInvalid(s)) {
                        continue;
                    }

                    SQLQuery sql = tm.getSessionFactory().getCurrentSession().createSQLQuery(s.trim());
                    sql.executeUpdate();
                }

            }
        });

    }

    /**
     * @param file
     * @return
     */
    private ClassPathResource getClassPathResource(String file, TestContext context) {

        return TestUtils.getSiblingResource(context.getTestClass(), file);
    }

    /**
     * @param cpr
     * @param br
     * @return
     */
    private BufferedReader _getBr(ClassPathResource cpr) {

        try {
            return new BufferedReader(new InputStreamReader(cpr.getInputStream(), "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            throw new KarakuRuntimeException(e);
        } catch (IOException e) {
            throw new KarakuRuntimeException("Can not load the file " + cpr.getFilename(), e);
        }
    }

    private ApplicationContext getApplicationContext(TestContext tc) {

        return tc.getApplicationContext();
    }

    /**
     * @param testContext
     * @param sqlFiles
     * @return
     */
    private List<String> getFiles(TestContext testContext, SQLFiles sqlFiles) {

        List<String> files = new ArrayList<String>(sqlFiles.value().length);
        for (String file : sqlFiles.value()) {
            String path = file.trim();
            if (path.equals(SQLFiles.NONE)) {
                continue;
            }
            if (path.equals(SQLFiles.DEFAULT) || "".equals(path)) {
                path = getSQLFile(testContext.getTestClass().getName());
            }
            if (files.contains(file)) {
                throw new IllegalArgumentException(
                        "The file " + path + ", is already defined in the anotation, in the form of:" + file);
            }
            if (!path.endsWith(".sql")) {
                path += ".sql";
            }
            files.add(path);
        }

        return files;
    }

    private HibernateTransactionManager getTransactionManager(TestContext context) {

        return context.getApplicationContext().getBean(HibernateTransactionManager.class);
    }

    /**
     * Retorna el nombre del archivo SQL base que se ejecuta antes de cualquier
     * test que herede de esta clase.
     * <p>
     * Implementacin por defecto retorna un archivo que esta en el mismo lugar
     * que el archivo .java.
     * </p>
     * 
     * @param path
     *            path del archivo. Es una cadena separada por puntos ( en vez
     *            de /) que no tiene una extensin.
     * @return Archivo vlido del classpath
     */
    public String getSQLFile(@NotNull String path) {

        String scriptPath = path.replaceAll("\\.", "/");
        scriptPath = scriptPath.replaceAll("\\$.*", "");
        scriptPath += ".sql";
        return scriptPath;
    }
}