/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (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.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * 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.queplix.core.utils.sql.vendor.oracle;

import com.queplix.core.jxb.entity.types.SqlSType;
import com.queplix.core.utils.StringHelper;
import com.queplix.core.utils.sql.generic.FloatParserImpl;
import com.queplix.core.utils.sql.generic.IntParserImpl;
import com.queplix.core.utils.sql.generic.LongParserImpl;
import com.queplix.core.utils.sql.generic.MemoParserImpl;
import com.queplix.core.utils.sql.generic.SqlWrapperImpl;
import com.queplix.core.utils.sql.generic.StringParserImpl;
import com.queplix.core.utils.sql.parser.BinaryParser;
import com.queplix.core.utils.sql.parser.DateParser;
import com.queplix.core.utils.sql.parser.FloatParser;
import com.queplix.core.utils.sql.parser.IntParser;
import com.queplix.core.utils.sql.parser.LongParser;
import com.queplix.core.utils.sql.parser.MemoParser;
import com.queplix.core.utils.sql.parser.StringParser;
import com.queplix.core.utils.sql.parser.TimeParser;
import com.queplix.core.utils.sql.parser.TimestampParser;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;

/**
 * Oracle SQL operations wrapper implementation.
 *
 * @author [ALB] Baranov Andrey
 * @author [ONZ] Oleg N. Zhovtanyuk
 * @version $Revision: 1.1.1.1 $ $Date: 2005/09/12 15:31:23 $
 */
public class SqlWrapperOracleImpl
        extends SqlWrapperImpl {

    // ================================================================== Fields

    // Parser implementations.
    // Change the generic implementations for database-specific ones, as needed.

    private final IntParserImpl intParser = new IntParserImpl();
    private final LongParserImpl longParser = new LongParserImpl();
    private final FloatParserImpl floatParser = new FloatParserImpl();
    private final StringParserImpl stringParser = new StringParserImpl();
    private final BinaryParserOracleImpl binaryParser
            = new BinaryParserOracleImpl();
    private final MemoParserOracleImpl memoParser = new MemoParserOracleImpl();
    private final MemoParserImpl memoLongParser = new MemoParserImpl();
    private final DateParserOracleImpl dateParser = new DateParserOracleImpl();
    private final TimestampParserOracleImpl timestampParser
            = new TimestampParserOracleImpl();
    private final TimeParserOracleImpl timeParser = new TimeParserOracleImpl();

    // ================================================ Interface implementation

    /* (non-Javadoc)
     * @see SqlWrapper#getIntParser()
     */

    public IntParser getIntParser() {
        return intParser;
    }

    /* (non-Javadoc)
     * @see SqlWrapper#getLongParser()
     */
    public LongParser getLongParser() {
        return longParser;
    }

    /* (non-Javadoc)
     * @see SqlWrapper#getFloatParser()
     */
    public FloatParser getFloatParser() {
        return floatParser;
    }

    /* (non-Javadoc)
     * @see SqlWrapper#getStringParser()
     */
    public StringParser getStringParser() {
        return stringParser;
    }

    /* (non-Javadoc)
     * @see SqlWrapper#getTimestampParser()
     */
    public TimestampParser getTimestampParser() {
        return timestampParser;
    }

    /* (non-Javadoc)
     * @see SqlWrapper#getDateParser()
     */
    public DateParser getDateParser() {
        return dateParser;
    }

    /* (non-Javadoc)
     * @see SqlWrapper#getTimeParser()
     */
    public TimeParser getTimeParser() {
        return timeParser;
    }

    /* (non-Javadoc)
     * @see SqlWrapper#getMemoParser()
     */
    public MemoParser getMemoParser() {
        return memoParser;
    }

    /* (non-Javadoc)
     * @see SqlWrapper#getMemoLongParser()
     */
    public MemoParser getMemoLongParser() {
        return memoLongParser;
    }

    /* (non-Javadoc)
     * @see SqlWrapper#getBinaryParser()
     */
    public BinaryParser getBinaryParser() {
        return binaryParser;
    }

    /* (non-Javadoc)
     * @see SqlWrapper#getNextSeq(Connection, String)
     */
    public long getNextSeq(Connection con, String name)
            throws SQLException {

        Statement stat = null;
        long keyValue;

        // Make SQL query.
        String sql = "SELECT " + name + ".NEXTVAL FROM DUAL";
        DEBUG("next sequence sql: " + sql);

        try {
            stat = con.prepareStatement(sql);
            ResultSet rs = stat.executeQuery(sql);
            if(rs.next()) {
                keyValue = rs.getLong(1);
            } else {
                keyValue = StringHelper.EMPTY_NUMBER;
            }

        } finally {
            closeConnection(stat);
        }

        // Ok.
        return keyValue;
    }

    /* (non-Javadoc)
     * @see SqlWrapper#getSoundex(Connection, String)
     */
    public String getSoundex(Connection con, String str)
            throws SQLException {
        String soundexSQL = "SELECT SOUNDEX( ? ) FROM DUAL";
        return getSoundexBySQL(con, soundexSQL, str);
    }

    /* (non-Javadoc)
     * @see SqlWrapper#getCurrentSchema(Connection)
     */
    public String getCurrentSchema(Connection con)
            throws SQLException {
        String schemaSQL
                = "SELECT SYS_CONTEXT('userenv','current_schema') FROM DUAL";
        return getCurrentSchemaBySQL(con, schemaSQL);
    }

    /* (non-Javadoc)
     * @see SqlWrapper#typeMapping(int, int)
     */
    public SqlSType typeMapping(int sqlType, int sqlColumnSize) {

        // Get type.
        SqlSType sqlSType = null;
        switch(sqlType) {
            case Types.DATE:
            case Types.TIMESTAMP:
                // Use TimeStamp parser for both sql types
                sqlSType = SqlSType.TIMESTAMP;
                break;
            default:
                // Call super method
                sqlSType = super.typeMapping(sqlType, sqlColumnSize);
        }

        // Ok.
        return sqlSType;
    }

    // ======================================================= Protected methods

    /* (non-Javadoc)
     * @see SqlWrapperImpl#throwSQLException(SQLException)
     */

    protected void throwSQLException(SQLException ex)
            throws SQLException {
        throw ex;
    }
}
