Package com.celum.dbtool

Source Code of com.celum.dbtool.Db$DbBuilder

/*****************************************************************************
* Copyright 2012 celum Slovakia s r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*****************************************************************************/
package com.celum.dbtool;

import com.celum.dbtool.configuration.DefaultMigrationConfiguration;
import com.celum.dbtool.installer.DbEventListener;
import com.celum.dbtool.installer.DbInstaller;
import com.celum.dbtool.resource.*;
import com.celum.dbtool.step.Version;
import com.celum.dbtool.sql.*;

import java.io.File;
import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
* This is the main facade for DB tool. You will use
* mostly this class.
*
* This class needs JDBC Connection but doesn't close or
* establish this connection. Connection management is in
* your application control.
*
* @author Zdenko Vrabel (zdenko.vrabel@celum.com)
*/
public class Db {

    /** database connection */
    private Connection dbConnection;

    /** resource from where scripts comes */
    private DbStepResource steps;

    /** variables which will be replaced as placeholders in SQLs */
    private Map<String, Object> variables;

    /** listener reacting on events like start executing SQL etc. */
    private DbEventListener eventListener;

    /** select that returns version for DB */
    private String versionSql;

    /** determines what strategy will be used for patching */
    private PatchStrategy patchStrategy = PatchStrategy.SIMPLE;

    /** Sql step which updates the version in DB */
    private String versionUpdateSqlScript;

    /** holds current DB version, it's filled by getCurrentVersion() method */
    private Version currentDbVersion;


    /**
     * Builder helps with construction of Db.
     */
    public class DbBuilder
    {
        private DbBuilder() { }

        public DbBuilder withEventsListener(DbEventListener eventListener)
        {
            eventListener = eventListener;
            return this;
        }

        public DbBuilder withVariable(String name, Object value)
        {
            variables.put(name, value);
            return this;
        }

        public DbBuilder withVariables(Map<?,?> vars)
        {
            if (vars != null) {
                for (Map.Entry<?,?> entry : vars.entrySet()) {
                    withVariable(entry.getKey().toString(), entry.getValue());
                }
            }
            return this;
        }

        public DbBuilder withProperties(Properties properties)
        {
            for (Map.Entry<Object,Object> e : properties.entrySet()) {
                withVariable(e.getKey().toString(), e.getValue().toString());
            }
            return this;
        }


        public DbBuilder withVersionUpdate(String versionUpdateSql)
        {
            Db.this.versionUpdateSqlScript = versionUpdateSql;
            return this;
        }


        public DbBuilder withVersionSql(String versionSql)
        {
            Db.this.versionSql = versionSql;
            return this;
        }


        public DbBuilder patchAs(PatchStrategy strategy)
        {
            Db.this.patchStrategy = strategy;
            return this;
        }


        public Db andDbSteps(DbStepResource steps)
        {
            if (steps == null) {
                throw new IllegalArgumentException("sqlScripts resource is null");
            }
            Db.this.steps = steps;
            return Db.this;
        }


        public Db andDbScriptsInDir(File dir)
        {
            return andDbSteps(new DirResource(dir));
        }


        public Db andDbScriptsInPackage(Package pckg)
        {
            return andDbSteps(new PackageResource(pckg));
        }


        public Db andDbScriptsInPackage(String packageName)
        {
            return andDbSteps(new PackageResource(packageName, this.getClass().getClassLoader()));
        }


        public DefaultMigrationConfiguration createDefaultMigrationConfiguration(String patchesTable)
        {
            return new DefaultMigrationConfiguration(this, patchesTable);
        }
    }

    /**
     * Hidden constructor. Use one of the factory methods.
     */
    private Db(Connection con) {
        this.dbConnection = con;
        this.variables = new HashMap<String, Object>();
    }


    /**
     * Method start building of Db instance with
     * various parameters.
     */
    public static DbBuilder withJdbcConnection(Connection con)
    {
        return (new Db(con)).new DbBuilder();
    }


    /**
     * method executes the scripts without any 'version' updating
     * checking etc. It's usable for DB initialization or dropping.
     */
    public void run()
    {
        DbInstaller installer = new DbInstaller(dbConnection, variables);
        installer.setEventListener(eventListener);
        installer.install(steps);
    }


    /**
     * install method instead of patch method executes all scripts without
     * any version check but the version table is updated anyway (if it's
     * defined via 'withVersionUpdate()'
     */
    public void install()
    {
        DbInstaller installer = new DbInstaller(dbConnection, variables);
        installer.setEventListener(eventListener);
        installer.setVersionUpdateSql(this.versionUpdateSqlScript);
        installer.install(steps);
    }


    /**
     * Method update the database to latest version. There are 2
     * strategies how patches could be applied.
     *
     * Simple strategy, when is 'versionSql' defined and
     * apply all patches greater than current DB. This strategy
     * is used when you've got VERSION table only with one value.
     *
     * Conditional strategy, when is precondition SQL defined. This
     * strategy apply all patches they're missing. This strategy
     * is used when you've got in VERSION table list of all applied
     * patches.
     *
     */
    public void patch()
    {
        DbStepResource filteredScripts = applyFilter();

        DbInstaller installer = new DbInstaller(dbConnection, variables);
        installer.setEventListener(eventListener);
        installer.setVersionUpdateSql(versionUpdateSqlScript);
        installer.install(filteredScripts);
    }


    /**
     * Method update the database to version you wish.
     */
    public void patchTo(Version v)
    {
        DbStepResource filteredScripts = applyFilter();
        filteredScripts = VersionFilter.filter(filteredScripts).smallerOrEqualsTo(v);

        DbInstaller installer = new DbInstaller(dbConnection, variables);
        installer.setEventListener(eventListener);
        installer.setVersionUpdateSql(versionUpdateSqlScript);
        installer.install(filteredScripts);
    }


    /**
     * get and fill the current DB version value to property
     */
    private void getCurrentDbVersion()
    {
        String version =
            Sql.asString(versionSql)
               .interceptingWith(new VelocityInterceptor(variables))
               .run(dbConnection)
               .andReturnString();

        currentDbVersion = Version.of(version);
    }


    /**
     * Method apply filter on resource by patching strategy
     */
    private DbStepResource applyFilter()
    {
        DbStepResource filteredScripts = null;
        switch (patchStrategy) {
            case SIMPLE:
                getCurrentDbVersion();
                filteredScripts =
                        VersionFilter
                                .filter(steps)
                                .largerThan(currentDbVersion);
                break;

            case CONDITIONAL:
                filteredScripts = new AppliedPatchesFiter(steps, dbConnection, versionSql, variables);
                break;
        }

        return filteredScripts;
    }
}
TOP

Related Classes of com.celum.dbtool.Db$DbBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.