de.ufinke.cubaja.sql.Sequence.java Source code

Java tutorial

Introduction

Here is the source code for de.ufinke.cubaja.sql.Sequence.java

Source

// Copyright (c) 2013, Uwe Finke. All rights reserved.
// Subject to BSD License. See "license.txt" distributed with this package.

package de.ufinke.cubaja.sql;

import java.sql.ResultSetMetaData;
import de.ufinke.cubaja.util.Text;
import org.apache.commons.logging.*;

public class Sequence {

    static private Text text = Text.getPackageInstance(Sequence.class);

    private SequenceConfig config;

    private Database database;

    private Query select;
    private Update lock;
    private Update delete;
    private Update update;
    private Update insert;

    private int selectFirstValuePos;
    private int selectLastValuePos;
    private int deleteOldValuePos;
    private int updateOldValuePos;
    private int updateNewValuePos;
    private int insertFirstValuePos;
    private int insertLastValuePos;

    private long currentValue;
    private long currentLimit;
    private long maxValue;

    private String string;
    private Log logger;

    public Sequence(SequenceConfig config) throws Exception {

        this.config = config.clone();

        if (config.isLog()) {
            logger = LogFactory.getLog(Sequence.class);
        }

        database = new Database(config.getDatabase());

        Sql sqlSelect = new Sql(getClass(), "sequence_select");
        sqlSelect.resolve("tableName", config.getTableName());
        sqlSelect.resolve("seqName", config.getSeqName());
        select = database.createQuery(sqlSelect);
        selectFirstValuePos = select.getColumnPosition("first_value");
        selectLastValuePos = select.getColumnPosition("last_value");

        Sql sqlLock = new Sql(getClass(), "sequence_lock");
        sqlLock.resolve("tableName", config.getTableName());
        sqlLock.resolve("seqName", config.getSeqName());
        lock = database.createUpdate(sqlLock);

        Sql sqlDelete = new Sql(getClass(), "sequence_delete");
        sqlDelete.resolve("tableName", config.getTableName());
        sqlDelete.resolve("seqName", config.getSeqName());
        delete = database.createUpdate(sqlDelete);
        deleteOldValuePos = delete.getVariablePositions("old_value")[0];

        Sql sqlUpdate = new Sql(getClass(), "sequence_update");
        sqlUpdate.resolve("tableName", config.getTableName());
        sqlUpdate.resolve("seqName", config.getSeqName());
        update = database.createUpdate(sqlUpdate);
        updateOldValuePos = update.getVariablePositions("old_value")[0];
        updateNewValuePos = update.getVariablePositions("new_value")[0];

        Sql sqlInsert = new Sql(getClass(), "sequence_insert");
        sqlInsert.resolve("tableName", config.getTableName());
        sqlInsert.resolve("seqName", config.getSeqName());
        insert = database.createUpdate(sqlInsert);
        insertFirstValuePos = insert.getVariablePositions("first_value")[0];
        insertLastValuePos = insert.getVariablePositions("last_value")[0];

        ResultSetMetaData meta = select.getMetaData();
        int precision = Math.min(18, meta.getPrecision(insertLastValuePos));
        maxValue = 1;
        for (int i = 0; i < precision; i++) {
            maxValue *= 10;
        }
        maxValue--;
        select.closeResultSet();
    }

    public String toString() {

        if (string == null) {
            StringBuilder sb = new StringBuilder(64);
            sb.append("Sequence[table=");
            try {
                sb.append(config.getTableName());
            } catch (Exception e) {
                sb.append("***notSpecified***");
            }
            sb.append(", seqName=");
            try {
                sb.append(config.getSeqName());
            } catch (Exception e) {
                sb.append("***notSpecified***");
            }
            sb.append(", blockSize=");
            sb.append(config.getBlockSize());
            sb.append("]");
            string = sb.toString();
        }

        return string;
    }

    public void close() throws Exception {

        execLock('c');
        if (currentValue < currentLimit) {
            execInsert(currentValue, currentLimit);
        }
        execCommit();

        select.close();
        lock.close();
        delete.close();
        update.close();
        insert.close();

        database.close();
    }

    public long nextValue() throws Exception {

        if (currentValue == currentLimit) {
            execLock('n');
            execSelect();
            execCommit();
        }

        return ++currentValue;
    }

    private void execLock(char flag) throws Exception {

        lock.setChar("lock_flag", flag);
        lock.executeUpdate();

        if (config.isLog()) {
            logger.debug(toString() + " lock: " + flag);
        }
    }

    private void execSelect() throws Exception {

        if (select.nextRow()) {
            currentValue = select.readLong(selectFirstValuePos);
            currentLimit = select.readLong(selectLastValuePos);
            select.closeResultSet();
            if (currentValue == currentLimit) {
                throw new SequenceException(
                        text.get("sequenceExhausted", Long.valueOf(maxValue), config.getSeqName()));
            } else if (currentLimit > currentValue + config.getBlockSize()) {
                currentLimit = currentValue + config.getBlockSize();
                execUpdate(currentValue, currentLimit);
            } else if (currentLimit == maxValue) {
                execUpdate(currentValue, currentLimit);
            } else {
                execDelete(currentValue);
            }
        } else {
            currentValue = 0;
            currentLimit = config.getBlockSize();
            execInsert(currentLimit, maxValue);
        }
    }

    private void execDelete(long oldValue) throws Exception {

        delete.setLong(deleteOldValuePos, oldValue);
        delete.executeUpdate();

        if (config.isLog()) {
            logger.debug(toString() + " delete: " + oldValue);
        }
    }

    private void execUpdate(long oldValue, long newValue) throws Exception {

        update.setLong(updateOldValuePos, oldValue);
        update.setLong(updateNewValuePos, newValue);
        update.executeUpdate();

        if (config.isLog()) {
            logger.debug(toString() + " update: " + oldValue + " -> " + newValue);
        }
    }

    private void execInsert(long firstValue, long lastValue) throws Exception {

        insert.setLong(insertFirstValuePos, firstValue);
        insert.setLong(insertLastValuePos, lastValue);
        insert.executeUpdate();

        if (config.isLog()) {
            logger.debug(toString() + " insert: " + firstValue + " .. " + lastValue);
        }
    }

    private void execCommit() throws Exception {

        database.commit();

        if (config.isLog()) {
            logger.debug(toString() + " commit");
        }
    }
}