All Downloads are FREE. Search and download functionalities are using the official Maven repository.

pl.kernelpanic.dbmonster.generator.StringKeyGenerator Maven / Gradle / Ivy

/* Version 1.0 based on Apache Software License 1.1
 *
 * Copyright (c) 2003 Piotr Maj and DBMonster developers. All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. The end-user documentation included with the redistribution, if any,
 *    must include the following acknowledgment:
 *
 *    "This product includes software developed by DBMonster developers
 *    (http://dbmonster.kernelpanic.pl/)."
 *
 *  Alternately, this acknowledgment may appear in the software itself,
 *  if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The name "DBMonster" must not be used to endorse or promote products
 *    derived from this software without prior written permission. For
 *    written permission, please contact [email protected].
 *
 * 5. Products derived from this software may not be called "DBMonster",
 *    nor may "DBMonster" appear in their name, without prior written
 *    permission of Piotr Maj.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE DBMONSTER DEVELOPERS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package pl.kernelpanic.dbmonster.generator;

import java.util.ArrayList;
import java.util.List;
import java.sql.ResultSet;

import org.apache.commons.logging.Log;

import pl.kernelpanic.dbmonster.DBMonster;
import pl.kernelpanic.dbmonster.DBMonsterContext;
import pl.kernelpanic.dbmonster.connection.ConnectionProvider;
import pl.kernelpanic.dbmonster.connection.Transaction;
import pl.kernelpanic.dbmonster.schema.Column;
import pl.kernelpanic.dbmonster.schema.Key;

/**
 * The string key generator uses sort of string magic known from Perl.
 * in short it starts from i.e. "aaaaa" and increment it by one:
 * "aaaab", "aaaac"....
 *
 * @author Piotr Maj <[email protected]>
 *
 * @version $Id: StringKeyGenerator.java,v 1.4 2006/01/05 16:29:37 majek Exp $
 */
public class StringKeyGenerator implements KeyGenerator, Initializable {

    /**
     * Default value.
     */
    public static final String DEFAULT_VALUE = "aaaaaaaa";

    /**
     * The key.
     */
    private Key key = null;

    /**
     * Holds a list of columns.
     */
    private List columns = new ArrayList();

    /**
     * Initial value. A special value of 0 (zero) means that
     * initial value should be taken from the database.
     */
    private String startValue = "0";

    /**
     * Context.
     */
    private DBMonsterContext context = null;

    /**
     * Next value.
     */
    private String nextValue = DEFAULT_VALUE;

    /**
     * Chars.
     */
    public static final char[] CHARS = new char[26];
    static {
        for (int i = 'a'; i <= 'z'; i++) {
            CHARS[i - 'a'] = (char) i;
        }
    }

    /**
     * Sets the key.
     *
     * @param k the key.
     */
    public void setKey(Key k) {
        key = k;
    }

    public Key getKey() {
        return key;
    }

    /**
     * Returns columns.
     *
     * @return a list of columns
     */
    public List getColumns() {
        return columns;
    }

    /**
     * Generates a primary key.
     *
     * @return a list of generated Columns.
     *
     * @throws Exception if generation fails
     */
    public List generate() throws Exception {
        Column column = (Column) columns.get(0);
        if (nextValue == null) {
            throw new Exception("No more values available (generator: "
                + getClass().getName() + ", table: "
                + key.getTable().getName() + ").");
        }
        column.setValue(nextValue);
        nextValue = incrementString(nextValue);
        return columns;
    }

    /**
     * @see Initializable#initialize(DBMonsterContext)
     */
    public void initialize(DBMonsterContext ctx) throws Exception {
        context = ctx;

        Log log = (Log) context.getProperty(DBMonster.LOGGER_KEY);
        if (log.isDebugEnabled()) {
            log.debug("Initializing generator <" + getClass().getName() + ">.");
        }

        if ("0".equals(startValue)) {
            ConnectionProvider connProv =
                (ConnectionProvider) context.getProperty(
                    DBMonster.CONNECTION_PROVIDER_KEY);
            Transaction tx = new Transaction(connProv);
            try {
                tx.begin();
                Column column = (Column) columns.get(0);
                String sql = "SELECT max(" + column.getName() + ") FROM "
                    + key.getTable().getName();

                if (log.isDebugEnabled()) {
                    log.debug(sql);
                }

                ResultSet rs = tx.executeQuery(sql);
                if (rs.next()) {
                    nextValue = rs.getString(1);
                    if (rs.wasNull() || "".equals(nextValue)) {
                        nextValue = DEFAULT_VALUE;
                    }
                    nextValue = incrementString(nextValue);
                } else {
                    nextValue = DEFAULT_VALUE;
                }
                tx.commit();
            } catch (Exception e) {
                if (log.isFatalEnabled()) {
                    log.fatal(e.getMessage());
                }
                tx.abort();
                throw e;
            } finally {
                tx.close();
            }
        } else {
            nextValue = startValue;
        }

        if (log.isDebugEnabled()) {
            log.debug("Initialization of generator <"
                + getClass().getName() + "> finished.");
        }
    }

    /**
     * Returns a column name.
     *
     * @return the name of the column.
     */
    public String getColumnName() {
        if (columns.size() == 1) {
            Column column = (Column) columns.get(0);
            if (column != null) {
                return column.getName();
            }
        }
        return null;
    }

    /**
     * Sets the column name and sets up the column.
     *
     * @param name the name of the column.
     */
    public void setColumnName(String name) {
        Column column = new Column();
        column.setName(name);
        columns = new ArrayList();
        columns.add(column);
    }

    /**
     * Increments a string.
     *
     * @param s string to increment
     * @return incremented string
     */
    private String incrementString(String s) {
        StringBuffer in = new StringBuffer(s);
        int pos = in.length() - 1;
        while (pos >= 0) {
            char c = in.charAt(pos);
            if (c != 'z') {
                in.setCharAt(pos, CHARS[c - 'a' + 1]);
                break;
            } else {
                in.setCharAt(pos, 'a');
            }
            --pos;
        }
        if (pos < 0) {
            return null; // no more strings
        } else {
            return in.toString();
        }
    }

    /**
     * Returns the start value.
     *
     * @return start value.
     */
    public String getStartValue() {
        return startValue;
    }

    /**
     * Sets the start value
     *
     * @param sv The startValue to set.
     */
    public void setStartValue(String sv) {
        startValue = sv;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy