scott.barleydb.test.TestBase.java Source code

Java tutorial

Introduction

Here is the source code for scott.barleydb.test.TestBase.java

Source

package scott.barleydb.test;

/*
 * #%L
 * BarleyDB
 * %%
 * Copyright (C) 2014 Scott Sinclair <scottysinclair@gmail.com>
 * %%
 * This program 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 3 of the
 * License, or (at your option) any later version.
 * 
 * This program 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 General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/lgpl-3.0.html>.
 * #L%
 */

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberInputStream;
import java.io.LineNumberReader;
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;

import javax.sql.DataSource;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.example.acl.model.AccessArea;
import org.example.acl.model.MacProxyFactory;
import org.example.acl.model.User;
import org.example.acl.query.QAccessArea;
import org.example.acl.query.QUser;
import org.example.etl.EtlSpec;
import org.example.etl.context.MiEntityContext;
import org.example.etl.model.BusinessType;
import org.example.etl.model.CsvMapping;
import org.example.etl.model.CsvStructure;
import org.example.etl.model.CsvStructureField;
import org.example.etl.model.CsvSyntaxModel;
import org.example.etl.model.MiProxyFactory;
import org.example.etl.model.SyntaxModel;
import org.example.etl.model.Template;
import org.example.etl.model.TemplateContent;
import org.example.etl.model.XmlMapping;
import org.example.etl.model.XmlStructure;
import org.example.etl.model.XmlSyntaxModel;
import org.example.etl.query.QBusinessType;
import org.example.etl.query.QCsvMapping;
import org.example.etl.query.QCsvStructure;
import org.example.etl.query.QCsvStructureField;
import org.example.etl.query.QCsvSyntaxModel;
import org.example.etl.query.QRawData;
import org.example.etl.query.QTemplate;
import org.example.etl.query.QTemplateBusinessType;
import org.example.etl.query.QTemplateContent;
import org.example.etl.query.QXmlMapping;
import org.example.etl.query.QXmlStructure;
import org.example.etl.query.QXmlSyntaxModel;
import org.example.etl.model.StructureType;
import org.example.etl.model.SyntaxType;
import org.junit.After;
import org.junit.Before;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.test.jdbc.JdbcTestUtils;
import org.springframework.test.jdbc.SimpleJdbcTestUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import scott.barleydb.api.config.Definitions;
import scott.barleydb.api.config.EntityType;
import scott.barleydb.api.core.Environment;
import scott.barleydb.api.core.entity.Entity;
import scott.barleydb.api.core.entity.EntityContext;
import scott.barleydb.api.core.entity.ProxyController;
import scott.barleydb.api.persist.PersistAnalyser;
import scott.barleydb.api.query.RuntimeProperties;
import scott.barleydb.api.query.RuntimeProperties.Concurrency;
import scott.barleydb.api.query.RuntimeProperties.ScrollType;
import scott.barleydb.api.specification.DefinitionsSpec;
import scott.barleydb.api.specification.SpecRegistry;
import scott.barleydb.build.specification.vendor.MySqlSpecConverter;
import scott.barleydb.server.jdbc.converter.LongToStringTimestampConverter;
import scott.barleydb.server.jdbc.persist.SequenceGenerator;
import scott.barleydb.server.jdbc.query.QueryPreProcessor;
import scott.barleydb.server.jdbc.vendor.HsqlDatabase;
import scott.barleydb.server.jdbc.vendor.MySqlDatabase;
import scott.barleydb.server.jdbc.vendor.OracleDatabase;
import scott.barleydb.server.jdbc.vendor.SqlServerDatabase;

@SuppressWarnings("deprecation")
public abstract class TestBase {

    public interface DatabaseTestSetup {
        String getDriverClassName();

        String getUrl();

        String getUser();

        String getPassword();

        String getSchemaName();

        Properties getConnectionProperties();
    }

    public static class HsqlDbTest implements DatabaseTestSetup {
        @Override
        public String getDriverClassName() {
            return "org.hsqldb.jdbcDriver";
        }

        @Override
        public String getUrl() {
            return "jdbc:hsqldb:mem:testdb";
        }

        @Override
        public String getUser() {
            return "sa";
        }

        @Override
        public String getPassword() {
            return "";
        }

        @Override
        public String getSchemaName() {
            return "hsqldb-schema.sql";
        }

        @Override
        public Properties getConnectionProperties() {
            Properties props = new Properties();
            return props;
        }
    }

    public static class MySqlDbTest implements DatabaseTestSetup {
        @Override
        public String getDriverClassName() {
            return "com.mysql.jdbc.Driver";
        }

        @Override
        public String getUrl() {
            return "jdbc:mysql://localhost:3306/sort";
        }

        @Override
        public String getUser() {
            return "root";
        }

        @Override
        public String getPassword() {
            return "s1ncla1r12";
        }

        @Override
        public String getSchemaName() {
            return "mysql-schema.sql";
        }

        @Override
        public Properties getConnectionProperties() {
            Properties props = new Properties();
            props.setProperty("CLIENT_MULTI_STATEMENTS", "true");
            return props;
        }
    }

    private static boolean databaseInitialized = false;
    protected static Environment env;
    protected static TestEntityContextServices entityContextServices;
    protected static String transformXml;
    protected static DatabaseTestSetup db = new HsqlDbTest();

    protected static final String namespace = "org.example.etl";
    protected static DataSource dataSource;
    protected EntityContext serverEntityContext;
    protected boolean autoCommitMode = false;

    protected void prepareData() throws Exception {
        executeScript("/clean.sql", false);
    }

    private void initDb() throws Exception {
        if (!databaseInitialized) {
            DriverManagerDataSource dmDataSource = new DriverManagerDataSource();
            dmDataSource.setDriverClassName(db.getDriverClassName());
            dmDataSource.setUrl(db.getUrl());
            dmDataSource.setUsername(db.getUser());
            dmDataSource.setPassword(db.getPassword());
            dmDataSource.setConnectionProperties(db.getConnectionProperties());
            dataSource = dmDataSource;

            if (db instanceof HsqlDbTest) {
                executeScript("/drop.sql", true);
                executeScript("/" + db.getSchemaName(), false);
            }
            databaseInitialized = true;
        }
    }

    public static void executeScript(String script, boolean continueOnError) throws Exception {
        System.out.println("EXECUTING SCRIPT " + script);
        LineNumberReader in = new LineNumberReader(
                new InputStreamReader(new ClassPathResource(script).getInputStream(), "UTF-8"));
        List<String> statements = new LinkedList<>();
        JdbcTestUtils.splitSqlScript(JdbcTestUtils.readScript(in), ';', statements);
        try (Connection c = dataSource.getConnection();) {
            c.setAutoCommit(false);
            try (Statement s = c.createStatement();) {
                for (String line : statements) {
                    try {
                        s.addBatch(line);
                    } catch (Exception x) {
                        if (!continueOnError) {
                            c.rollback();
                            throw x;
                        }
                        System.err.println(x.getMessage());
                    }
                }
                try {
                    s.executeBatch();
                } catch (Exception x) {
                    if (!continueOnError) {
                        c.rollback();
                        throw x;
                    }
                    System.err.println(x.getMessage());
                }
                c.commit();
            }
        } catch (Exception x) {
            if (!continueOnError)
                throw x;
        }
        System.out.println("FINISHED EXECUTING SCRIPT " + script);
    }

    public static void setupDefs() throws Exception {
        if (env != null) {
            return;
        }

        entityContextServices = new TestEntityContextServices(dataSource);
        env = new Environment(entityContextServices);
        /*
         * The server executes by default in the same context
         * and provides reasonable values for result-set scrolling and fetching
         */
        env.setDefaultRuntimeProperties(new RuntimeProperties().concurrency(Concurrency.READ_ONLY).fetchSize(100)
                .executeInSameContext(true).scrollType(ScrollType.FORWARD_ONLY));
        env.setQueryPreProcessor(new QueryPreProcessor());

        entityContextServices.setEnvironment(env);
        env.loadDefinitions();

        Connection connection = dataSource.getConnection();
        DatabaseMetaData metadata = connection.getMetaData();
        entityContextServices.addDatabases(new HsqlDatabase(metadata), new OracleDatabase(metadata),
                new SqlServerDatabase(metadata), new MySqlDatabase(metadata));

        connection.close();

        class TestSequenceGenerator implements SequenceGenerator {
            Long key = 1l;

            @Override
            public Object getNextKey(EntityType entityType) {
                return key++;
            }
        }
        ;

        entityContextServices.setSequenceGenerator(new TestSequenceGenerator());
        entityContextServices.register(new LongToStringTimestampConverter());

        env.addDefinitions(Definitions
                .create(loadDefinitions("src/test/java/org/example/acl/aclspec.xml", "org.example.acl")));
        env.addDefinitions(Definitions
                .create(loadDefinitions("src/test/java/org/example/etl/etlspec.xml", "org.example.etl")));

        env.getDefinitions("org.example.acl").registerQueries(new QUser(), new QAccessArea());

        env.getDefinitions("org.example.acl").registerProxyFactory(new MacProxyFactory());

        env.getDefinitions("org.example.etl").registerQueries(new QXmlSyntaxModel(), new QXmlStructure(),
                new QXmlMapping(), new QCsvSyntaxModel(), new QCsvStructure(), new QCsvStructureField(),
                new QCsvMapping(), new QTemplate(), new QTemplateContent(), new QTemplateBusinessType(),
                new QBusinessType(), new QRawData());

        env.getDefinitions("org.example.etl").registerProxyFactory(new MiProxyFactory());

        transformXml = "<?xml version=\"1.0\"?>" + "<xsl:stylesheet version=\"1.0\" "
                + "xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" + "<xsl:strip-space elements=\"*\" />"
                + "<xsl:output method=\"xml\" indent=\"yes\" />" + "" + "<xsl:template match=\"node() | @*\">"
                + "<xsl:copy>" + "<xsl:apply-templates select=\"node() | @*\" />" + "</xsl:copy>"
                + "</xsl:template>" + "</xsl:stylesheet>";
    }

    @Before
    public void setup() throws Exception {
        initDb();
        setupDefs();
        prepareData();

        /*
         * create a session with the definitions above, the query registry and a datasource.
         */
        serverEntityContext = new MiEntityContext(env);
        serverEntityContext.setAutocommit(autoCommitMode);
    }

    @After
    public void tearDown() throws Exception {
        if (!serverEntityContext.getAutocommit()) {
            serverEntityContext.rollback();
        }
    }

    private static DefinitionsSpec loadDefinitions(String path, String namespace) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(SpecRegistry.class, StructureType.class, SyntaxType.class,
                EtlSpec.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        SpecRegistry registry = (SpecRegistry) unmarshaller.unmarshal(new File(path));
        DefinitionsSpec spec = registry.getDefinitionsSpec(namespace);
        if (spec == null) {
            throw new IllegalStateException("Could not load definitions " + namespace);
        }

        if (db instanceof MySqlDbTest) {
            spec = MySqlSpecConverter.convertSpec(spec);
        }
        return spec;
    }

    protected Entity toEntity(Object object) {
        return ((ProxyController) object).getEntity();
    }

    protected void printEntityContext(EntityContext entityContext) throws Exception {
        Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        Element el = entityContext.toXml(doc);
        doc.appendChild(el);
        Transformer transformer = TransformerFactory.newInstance()
                .newTransformer(new StreamSource(new ByteArrayInputStream(transformXml.getBytes("UTF-8"))));
        transformer.transform(new DOMSource(doc), new StreamResult(System.out));
        System.out.flush();
    }

    protected static void print(String prefix, AccessArea accessArea) {
        System.out.println(prefix + "AccessArea Id   " + accessArea.getId());
        System.out.println(prefix + "AccessArea Name " + accessArea.getName());
        if (accessArea.getParent() != null) {
            System.out.println(prefix + "AA Parent Id " + accessArea.getParent().getId());
        }
        for (AccessArea child : accessArea.getChildren()) {
            print(prefix + "  ", child);
        }
    }

    protected static void print(String prefix, Template template) {
        System.out.println(prefix + "Template Id   " + template.getId());
        System.out.println(prefix + "Template Name " + template.getName());
        if (template.getContents() != null) {
            for (TemplateContent tc : template.getContents()) {
                print(prefix + "  ", tc);
            }
        }
        if (template.getBusinessTypes() != null) {
            for (BusinessType dt : template.getBusinessTypes()) {
                print(prefix + "  ", dt);
            }
        }
    }

    protected void printCreateAnalysis(PersistAnalyser analyser) {
        System.out.println();
        System.out.println("------------------------------------");
        System.out.println("------------ Create List ------------");
        System.out.println("-------------------------------------");
        for (Entity entity : analyser.getCreateGroup().getEntities()) {
            System.out.println(entity);
        }
        System.out.println();
    }

    protected void printUpdateAnalysis(PersistAnalyser analyser) {
        System.out.println();
        System.out.println("-------------------------------------");
        System.out.println("------------ Update List ------------");
        System.out.println("-------------------------------------");
        for (Entity entity : analyser.getUpdateGroup().getEntities()) {
            System.out.println(entity);
        }
        System.out.println();
    }

    protected void printDeleteAnalysis(PersistAnalyser analyser) {
        System.out.println();
        System.out.println("-------------------------------------");
        System.out.println("------------ Delete List ------------");
        System.out.println("-------------------------------------");
        for (Entity entity : analyser.getDeleteGroup().getEntities()) {
            System.out.println(entity);
        }
        System.out.println();
    }

    protected void printDependsOnAnalysis(PersistAnalyser analyser) {
        System.out.println();
        System.out.println("-------------------------------------");
        System.out.println("------------ Depends on List ------------");
        System.out.println("-------------------------------------");
        for (Entity entity : analyser.getDeleteGroup().getEntities()) {
            System.out.println(entity);
        }
        System.out.println();
    }

    protected void printAnalysis(PersistAnalyser analyser) {
        printCreateAnalysis(analyser);
        printUpdateAnalysis(analyser);
        printDeleteAnalysis(analyser);
        printDependsOnAnalysis(analyser);
    }

    protected static void print(String prefix, TemplateContent tc) {
        System.out.println(prefix + "Content Id   " + tc.getId());
        System.out.println(prefix + "Content Name " + tc.getName());
    }

    protected static void print(String prefix, BusinessType datatype) {
        System.out.println(prefix + "BusinessType Id   " + datatype.getId());
        System.out.println(prefix + "BusinessType Name " + datatype.getName());
    }

    protected static void print(String prefix, SyntaxModel syntaxModel) {
        if (syntaxModel instanceof XmlSyntaxModel) {
            print(prefix, (XmlSyntaxModel) syntaxModel);
        } else if (syntaxModel instanceof CsvSyntaxModel) {
            print(prefix, (CsvSyntaxModel) syntaxModel);
        }
    }

    protected static void print(String prefix, XmlSyntaxModel syntaxModel) {
        System.out.println(prefix + "XMLSyntax Id   " + syntaxModel.getId());
        System.out.println(prefix + "XMLSyntax Name " + syntaxModel.getName());
        System.out.println(prefix + "XMLSyntax JoinType " + syntaxModel.getSyntaxType());
        if (syntaxModel.getUser() != null) {
            print(prefix + "  ", syntaxModel.getUser());
        }
        if (syntaxModel.getStructure() != null) {
            print(prefix + "  ", syntaxModel.getStructure());
        }
        if (syntaxModel.getMappings() != null) {
            for (XmlMapping mapping : syntaxModel.getMappings()) {
                print(prefix + "  ", mapping);
            }
        }
    }

    protected static void print(String prefix, CsvSyntaxModel syntaxModel) {
        System.out.println(prefix + "CSVSyntax Id   " + syntaxModel.getId());
        System.out.println(prefix + "CSVSyntax Name " + syntaxModel.getName());
        System.out.println(prefix + "CSVSyntax JoinType " + syntaxModel.getSyntaxType());
        if (syntaxModel.getUser() != null) {
            print(prefix + "  ", syntaxModel.getUser());
        }
        if (syntaxModel.getStructure() != null) {
            print(prefix + "  ", syntaxModel.getStructure());
        }
        if (syntaxModel.getMappings() != null) {
            for (CsvMapping mapping : syntaxModel.getMappings()) {
                print(prefix + "  ", mapping);
            }
        }
    }

    protected static void print(String prefix, User user) {
        System.out.println(prefix + "User Id   " + user.getId());
        System.out.println(prefix + "User Name " + user.getName());
    }

    protected static void print(String prefix, XmlStructure structure) {
        System.out.println(prefix + "Structure Id   " + structure.getId());
        System.out.println(prefix + "Structure Name " + structure.getName());
    }

    protected static void print(String prefix, CsvStructure structure) {
        System.out.println(prefix + "Structure Id   " + structure.getId());
        System.out.println(prefix + "Structure Name " + structure.getName());
        if (structure.getFields() != null) {
            for (CsvStructureField field : structure.getFields()) {
                print(prefix + "  ", field);
            }
        }
    }

    protected static void print(String prefix, CsvStructureField field) {
        System.out.println(prefix + "Field Id       " + field.getId());
        System.out.println(prefix + "Field Name     " + field.getName());
        System.out.println(prefix + "Field Index    " + field.getColumnIndex());
        System.out.println(prefix + "Field Optional " + field.getOptional());
    }

    protected static void print(String prefix, CsvMapping mapping) {
        System.out.println(prefix + "Mapping Id      " + mapping.getId());
        System.out.println(prefix + "Mapping Column   " + mapping.getStructureField().getColumnIndex());
        System.out.println(prefix + "Mapping Target  " + mapping.getTargetFieldName());
        System.out.println(prefix + "Mapping SyntaxModel  " + mapping.getSyntax().getId());
    }

    protected static void print(String prefix, XmlMapping mapping) {
        System.out.println(prefix + "Mapping Id      " + mapping.getId());
        System.out.println(prefix + "Mapping XPath   " + mapping.getXpath());
        System.out.println(prefix + "Mapping Target  " + mapping.getTargetFieldName());
        System.out.println(prefix + "Mapping SyntaxModel  " + mapping.getSyntax().getId());
        if (mapping.getSubSyntax() != null) {
            XmlSyntaxModel sub = mapping.getSubSyntax();
            if (sub != null) {
                print(prefix + "  ", sub);
            }
        }
    }

}