/*
 * 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.error.GenericSystemException;
import com.queplix.core.utils.StringHelper;
import oracle.jdbc.driver.OracleCallableStatement;

import java.io.IOException;
import java.io.Reader;
import java.io.Serializable;
import java.io.StringReader;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Helper class to work with Oracle "LONG" data type.
 * This class MUST be thread-safe.
 *
 * @author [ALB] Baranov Andrey
 * @version $Revision: 1.1.1.1 $ $Date: 2005/09/12 15:31:23 $
 */
public class OracleLong
        implements Serializable {

    // ========================================================== Public methods

    /**
     * Sets the CLOB into the PreparedStement object.
     *
     * @param stat PreparedStement object to set CLOB into
     * @param pos  substitution position in statement
     * @param data CLOB to set
     */
    public void setObject(PreparedStatement stat, int pos, char[] data) {
        try {
            // Clear string
            String text = new String(data);
            text = StringHelper.clear(text);

            StringReader rdr = new StringReader(text);
            stat.setCharacterStream(pos, rdr, text.length());

        } catch (SQLException ex) {
            throw new GenericSystemException(
                    "SQL exception: " + ex.getMessage(), ex);
        }
    }

    /**
     * Retrives the CLOB object from ResultSet object.
     *
     * @param rs  ResultSet object to retrieve the CLOB from
     * @param pos substitution position in statement
     * @return CLOB data
     */
    public char[] getObject(ResultSet rs, int pos) {
        try {
            Reader rdr = rs.getCharacterStream(pos);
            return (rdr == null) ? null:retriveObject(rdr).toCharArray();

        } catch (SQLException ex) {
            throw new GenericSystemException(
                    "SQL exception: " + ex.getMessage(), ex);
        }
    }

    /**
     * Retrives the CLOB object from CallableStatement object.
     *
     * @param cs  CallableStatement object to retrieve the CLOB from
     * @param pos substitution position in statement
     * @return CLOB data
     */
    public char[] getObject(CallableStatement cs, int pos) {
        try {
            Reader rdr = ((OracleCallableStatement) cs).getCharacterStream(pos);
            return (rdr == null) ? null:retriveObject(rdr).toCharArray();
        } catch (SQLException ex) {
            throw new GenericSystemException(
                    "SQL exception: " + ex.getMessage(), ex);
        }
    }

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

    /*
     * <p>Retrive the Long object from ResultSet.</p>
     */

    protected String retriveObject(Reader reader) {
        StringBuffer data = null;

        try {
            int len = 255;
            char[] buffer = new char[len];
            data = new StringBuffer();

            int i = 0;
            while((i = reader.read(buffer)) != -1) {
                data.append(buffer, 0, i);
            }

        } catch (IOException ioex) {
            ioex.printStackTrace();
            throw new GenericSystemException(
                    "I/O exception: " + ioex.getMessage(), ioex);

        } finally {
            try {
                if(reader != null) {
                    reader.close();
                }
            } catch (IOException ex) {
            }
        }

        return data.toString();
    }
}
