/*

    @author DanielD

    ========== licence begin GPL
    Copyright (C) 2002-2003 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end


*/

package com.sap.dbtech.procserver;

import java.sql.*;
import java.util.*;

import com.sap.dbtech.jdbc.DBProcParameterInfo;
import com.sap.dbtech.jdbc.exceptions.*;
import com.sap.dbtech.jdbc.translators.*;
import com.sap.dbtech.jdbc.packet.*;
import com.sap.dbtech.vsp001.*;
import com.sap.dbtech.util.*;

/**
 *
 */
public class ProcParameterList
implements com.sap.dbtech.jdbc.translators.SQLParamController
{
    private DBTechTranslator [] translators;
    private StructuredMem dataMem;
    private Object [] outputArgs;
    private java.sql.ParameterMetaData metaData;
    private boolean lastWasNull = false;
    /**
     * creates a new ProcParameterList
     */
    ProcParameterList (
        ReplyPacket replyPacket,
        DBTechTranslator [] translators,
        DBProcParameterInfo[] procParameters)
    {
        try {
            if (translators == null) {
                translators = createTranslators (replyPacket, procParameters);
            }
            this.translators = translators;
            this.metaData = new com.sap.dbtech.jdbc.ParameterMetaDataSapDB (this.translators);
            replyPacket.findPart (PartKind.Data_C);
            this.dataMem = replyPacket.getPointer (replyPacket.getPartDataPos ());
            this.outputArgs = new Object [translators.length];
        }
        catch (Throwable exc) {
            Log.traceException (exc);
            throw new Error (exc.getMessage ());
        }
    }
    /**
     * creates a new ProcParameterList
     */
    ProcParameterList (ReplyPacket replyPacket)
    {
        this (replyPacket, null, null);
    }
    
    /**
     *
     */
    private DBTechTranslator[] createTranslators (ReplyPacket replyPacket,
        DBProcParameterInfo[] procParameters)
    throws Throwable
    {
        replyPacket.findPart (PartKind.Shortinfo_C);
        return replyPacket.parseShortFields (false, procParameters);
    }
    /**
     *
     */
    public java.sql.ParameterMetaData 
    getParameterMetaData ()
    {
        return this.metaData;
    }
    /**
     *
     */
    boolean 
    hasOutputParameter ()
    {
        for (int i = 0; i < this.translators.length; ++i) {
            if (this.translators [i].isOutput()) {
                return true;
            }
        }
        return false;
    }
    /**
     *
     */
    void 
    copyToOutputPacket (
        DataPart dataPart)
    throws java.sql.SQLException
    {
        for (int i = 0; i < this.translators.length; ++i) {
            if (this.translators [i].isOutput()) {
                Log.log ("Out " + (i + 1) + " => " + this.outputArgs [i]);
                this.translators [i].putProcOutput (dataPart, this.outputArgs [i]);
            }
        }
    }
    /**
     * findColumn method comment.
     */
    private DBTechTranslator findColInfo (
        int colIndex)
    throws SQLException
    {
        DBTechTranslator info;

        try {
            info = this.translators [colIndex - 1];
        }
        catch (ArrayIndexOutOfBoundsException exc) {
            throw new JDBCDriverException
                (MessageTranslator.translate(MessageKey.ERROR_COLINDEX_NOTFOUND,
                                             Integer.toString(colIndex)),
                 this);
        }
        return info;
    }

    /**
     * Gets the value of a JDBC <code>NUMERIC</code> parameter as a
     * <code>java.math.BigDecimal</code> object with as many digits to the
     * right of the decimal point as the value contains.
     * @param parameterIndex the first parameter is 1, the second is 2,
     * and so on
     * @return the parameter value in full precision.  If the value is
     * SQL NULL, the result is <code>null</code>.
     * @exception SQLException if a database access error occurs
     */
    public java.math.BigDecimal getBigDecimal(
        int parameterIndex)
    throws SQLException
    {
        return this.findColInfo (parameterIndex).getBigDecimal (this, this.dataMem);
    }
    /**
     * getBigDecimal method comment.
     */
    public java.math.BigDecimal getBigDecimal(
        int parameterIndex,
        int scale)
    throws java.sql.SQLException
    {
        return this.findColInfo (parameterIndex).getBigDecimal (scale, this, this.dataMem);
    }
    /**
     * getBoolean method comment.
     */
    public boolean getBoolean(
        int parameterIndex)
    throws java.sql.SQLException
    {
        return this.findColInfo (parameterIndex).getBoolean (this, this.dataMem);
    }
    /**
     * getByte method comment.
     */
    public byte getByte(
        int parameterIndex)
    throws java.sql.SQLException
    {
        return this.findColInfo (parameterIndex).getByte (this, this.dataMem);
    }
    /**
     * getBytes method comment.
     */
    public byte[] getBytes(
        int parameterIndex)
    throws java.sql.SQLException
    {
        return this.findColInfo (parameterIndex).getBytes (this, this.dataMem);
    }
    /**
     * getDate method comment.
     */
    public java.sql.Date getDate(
        int parameterIndex)
    throws java.sql.SQLException
    {
        return this.findColInfo (parameterIndex).getDate (this, this.dataMem,null);
    }
    /**
     * Gets the value of a JDBC <code>DATE</code> parameter as a
     * <code>java.sql.Date</code> object, using
     * the given <code>Calendar</code> object
     * to construct the date.
     * With a <code>Calendar</code> object, the driver
     * can calculate the date taking into account a custom timezone and locale.
     * If no <code>Calendar</code> object is specified, the driver uses the
     * default timezone and locale.
     *
     * @param parameterIndex the first parameter is 1, the second is 2,
     * and so on
     * @param cal the <code>Calendar</code> object the driver will use
     *            to construct the date
     * @return the parameter value.  If the value is SQL NULL, the result is
     * <code>null</code>.
     * @exception SQLException if a database access error occurs
     */
    public java.sql.Date getDate(int parameterIndex,
                                 Calendar cal)
        throws SQLException
    {
        return this.findColInfo (parameterIndex).getDate (this, this.dataMem,cal);
    }

    /**
     * getDouble method comment.
     */
    public double getDouble(
        int parameterIndex)
    throws java.sql.SQLException
    {
        return this.findColInfo (parameterIndex).getDouble (this, this.dataMem);
    }
    /**
     * getFloat method comment.
     */
    public float getFloat(
        int parameterIndex)
    throws java.sql.SQLException
    {
        return this.findColInfo (parameterIndex).getFloat (this, this.dataMem);
    }
    /**
     * getInt method comment.
     */
    public int getInt(
        int parameterIndex)
    throws java.sql.SQLException
    {
        return this.findColInfo (parameterIndex).getInt (this, this.dataMem);
    }
    /**
     * getLong method comment.
     */
    public long getLong(
        int parameterIndex)
    throws java.sql.SQLException
    {
        return this.findColInfo (parameterIndex).getLong (this, this.dataMem);
    }

    /**
     * getObject method comment.
     */
    public Object getObject(
        int parameterIndex)
    throws java.sql.SQLException
    {
        return this.findColInfo (parameterIndex).getObject (this, this.dataMem);
    }
    /**
     * getShort method comment.
     */
    public short getShort(
        int parameterIndex)
    throws java.sql.SQLException
    {
        return this.findColInfo (parameterIndex).getShort (this, this.dataMem);
    }
    /**
     * getString method comment.
     */
    public String getString(
        int parameterIndex)
    throws java.sql.SQLException
    {
        return this.findColInfo (parameterIndex).getString (this, this.dataMem);
    }
    /**
     * getTime method comment.
     */
    public java.sql.Time getTime(
        int parameterIndex)
    throws java.sql.SQLException
    {
        return this.findColInfo (parameterIndex).getTime (this, this.dataMem,null);
    }
    /**
     * Gets the value of a JDBC <code>TIME</code> parameter as a
     * <code>java.sql.Time</code> object, using
     * the given <code>Calendar</code> object
     * to construct the time.
     * With a <code>Calendar</code> object, the driver
     * can calculate the time taking into account a custom timezone and locale.
     * If no <code>Calendar</code> object is specified, the driver uses the
     * default timezone and locale.
     *
     * @param parameterIndex the first parameter is 1, the second is 2,
     * and so on
     * @param cal the <code>Calendar</code> object the driver will use
     *            to construct the time
     * @return the parameter value; if the value is SQL NULL, the result is
     * <code>null</code>.
     * @exception SQLException if a database access error occurs
     */
    public java.sql.Time getTime(
        int parameterIndex,
        Calendar cal)
    throws SQLException
    {
        return this.findColInfo (parameterIndex).getTime (this, this.dataMem,cal);
    }

    /**
     * getTimestamp method comment.
     */
    public java.sql.Timestamp getTimestamp(int parameterIndex) throws java.sql.SQLException {
        return this.findColInfo (parameterIndex).getTimestamp (this, this.dataMem,null);
    }
    /**
     * Gets the value of a JDBC <code>TIMESTAMP</code> parameter as a
     * <code>java.sql.Timestamp</code> object, using
     * the given <code>Calendar</code> object to construct
     * the <code>Timestamp</code> object.
     * With a <code>Calendar</code> object, the driver
     * can calculate the timestamp taking into account a custom timezone and locale.
     * If no <code>Calendar</code> object is specified, the driver uses the
     * default timezone and locale.
     *
     *
     * @param parameterIndex the first parameter is 1, the second is 2,
     * and so on
     * @param cal the <code>Calendar</code> object the driver will use
     *            to construct the timestamp
     * @return the parameter value.  If the value is SQL NULL, the result is
     * <code>null</code>.
     * @exception SQLException if a database access error occurs
     */
    public java.sql.Timestamp getTimestamp(int parameterIndex,
                                           Calendar cal)
        throws SQLException
    {
        return this.findColInfo (parameterIndex).getTimestamp (this, this.dataMem,cal);
    }

    /**
     * setBigDecimal method comment.
     */
    public void setBigDecimal(
        int parameterIndex,
        java.math.BigDecimal x)
    throws java.sql.SQLException
    {
        Object arg = this.findColInfo (parameterIndex).transBigDecimalForInput (x);
        this.outputArgs [parameterIndex - 1] = arg;
    }
    /**
     * setBoolean method comment.
     */
    public void setBoolean(
        int parameterIndex,
        boolean x)
    throws java.sql.SQLException
    {
        Object arg = this.findColInfo (parameterIndex).transBooleanForInput (x);
        this.outputArgs [parameterIndex - 1] = arg;
    }
    /**
     * setByte method comment.
     */
    public void setByte(
        int parameterIndex,
        byte x)
    throws java.sql.SQLException
    {
        Object arg = this.findColInfo (parameterIndex).transByteForInput (x);
        this.outputArgs [parameterIndex - 1] = arg;
    }
    /**
     * setBytes method comment.
     */
    public void setBytes(
        int parameterIndex,
        byte[] x)
    throws java.sql.SQLException
    {
        Object arg = this.findColInfo (parameterIndex).transBytesForInput (x);
        this.outputArgs [parameterIndex - 1] = arg;
    }
    /**
     * setDate method comment.
     */
    public void setDate(
        int parameterIndex,
        java.sql.Date x)
    throws java.sql.SQLException
    {
        this.setDate(parameterIndex,x,null);
    }
    /**
     * JDBC 2.0
     *
     * Sets the designated parameter to a java.sql.Date value,
     * using the given <code>Calendar</code> object.  The driver uses
     * the <code>Calendar</code> object to construct an SQL DATE,
     * which the driver then sends to the database.  With a
     * a <code>Calendar</code> object, the driver can calculate the date
     * taking into account a custom timezone and locale.  If no
     * <code>Calendar</code> object is specified, the driver uses the default
     * timezone and locale.
     *
     * @param parameterIndex the first parameter is 1, the second is 2, ...
     * @param x the parameter value
     * @param cal the <code>Calendar</code> object the driver will use
     *            to construct the date
     * @exception SQLException if a database access error occurs
     */
    public void setDate(
        int parameterIndex,
        java.sql.Date x,
        Calendar cal)
    throws SQLException
    {
       if(cal==null) {
         cal=Calendar.getInstance();
       }
       Object arg = this.findColInfo (parameterIndex).transDateForInput (x,cal);
       this.outputArgs [parameterIndex - 1] = arg;
    }

    /**
     * setDouble method comment.
     */
    public void setDouble(
        int parameterIndex,
        double x)
    throws java.sql.SQLException
    {
        Object arg = this.findColInfo (parameterIndex).transDoubleForInput (x);
        this.outputArgs [parameterIndex - 1] = arg;
    }
    /**
     * setFloat method comment.
     */
    public void setFloat(
        int parameterIndex,
        float x)
    throws java.sql.SQLException
    {
        Object arg = this.findColInfo (parameterIndex).transFloatForInput (x);
        this.outputArgs [parameterIndex - 1] = arg;
    }
    /**
     * setInt method comment.
     */
    public void setInt(int parameterIndex,
        int x)
    throws java.sql.SQLException
    {
        Object arg = this.findColInfo (parameterIndex).transIntForInput (x);
        this.outputArgs [parameterIndex - 1] = arg;
    }
    /**
     * setLong method comment.
     */
    public void setLong(
        int parameterIndex,
        long x)
    throws java.sql.SQLException
    {
        Object arg = this.findColInfo (parameterIndex).transLongForInput (x);
        this.outputArgs [parameterIndex - 1] = arg;
    }
    /**
     * setNull method comment.
     */
    public void setNull(
        int parameterIndex,
        int sqlType)
    throws java.sql.SQLException
    {
        this.outputArgs [parameterIndex - 1] = null;
    }
    /**
     * JDBC 2.0
     *
     * Sets the designated parameter to SQL NULL.  This version of setNull should
     * be used for user-named types and REF type parameters.  Examples
     * of user-named types include: STRUCT, DISTINCT, JAVA_OBJECT, and
     * named array types.
     *
     * <P><B>Note:</B> To be portable, applications must give the
     * SQL type code and the fully-qualified SQL type name when specifying
     * a NULL user-defined or REF parameter.  In the case of a user-named type
     * the name is the type name of the parameter itself.  For a REF
     * parameter the name is the type name of the referenced type.  If
     * a JDBC driver does not need the type code or type name information,
     * it may ignore it.
     *
     * Although it is intended for user-named and Ref parameters,
     * this method may be used to set a null parameter of any JDBC type.
     * If the parameter does not have a user-named or REF type, the given
     * typeName is ignored.
     *
     *
     * @param parameterIndex the first parameter is 1, the second is 2, ...
     * @param sqlType a value from java.sql.Types
     * @param typeName the fully-qualified name of an SQL user-named type,
     *  ignored if the parameter is not a user-named type or REF
     * @exception SQLException if a database access error occurs
     */
    public void setNull (
        int paramIndex,
        int sqlType,
        String typeName)
    throws java.sql.SQLException
    {
        this.setNull (paramIndex, sqlType);
    }
    /**
     * setObject method comment.
     */
    public void setObject(
        int parameterIndex,
        Object x)
    throws java.sql.SQLException
    {
        Object arg = this.findColInfo (parameterIndex).transObjectForInput (x);
        this.outputArgs [parameterIndex - 1] = arg;
    }
    /**
     * setObject method comment.
     */
    public void setObject(
        int parameterIndex,
        Object x,
        int targetSqlType)
    throws java.sql.SQLException
    {
        // specials for JDBC Compliance
        switch(targetSqlType) {
        case Types.INTEGER:
            if(x instanceof Number) {
                Number n=(Number)x;
                this.setInt(parameterIndex, n.intValue());
                return;
            }
        case Types.BIGINT:
            if(x instanceof Number) {
                Number n=(Number)x;
                this.setLong(parameterIndex, n.longValue());
                return;
            }
        }
        this.setObject (parameterIndex, x);
    }
    /**
     * setObject method comment.
     */
    public void setObject(
        int parameterIndex,
        Object x,
        int targetSqlType,
        int scale)
    throws java.sql.SQLException
    {
        // ignore targetSqlType
        this.setObject (parameterIndex, x, scale);
    }
    /**
     * setShort method comment.
     */
    public void setShort(
        int parameterIndex,
        short x)
    throws java.sql.SQLException
    {
        Object arg = this.findColInfo (parameterIndex).transShortForInput (x);
        this.outputArgs [parameterIndex - 1] = arg;
    }
    /**
     * setString method comment.
     */
    public void setString(
        int parameterIndex,
        String x)
    throws java.sql.SQLException
    {
        Object arg = this.findColInfo (parameterIndex).transStringForInput (x);
        this.outputArgs [parameterIndex - 1] = arg;
    }
    /**
     * setTime method comment.
     */
    public void setTime(
        int parameterIndex,
        java.sql.Time x)
    throws java.sql.SQLException
    {
       this.setTime(parameterIndex,x, null);
    }
    /**
     * JDBC 2.0
     *
     * Sets the designated parameter to a java.sql.Time value,
     * using the given <code>Calendar</code> object.  The driver uses
     * the <code>Calendar</code> object to construct an SQL TIME,
     * which the driver then sends to the database.  With a
     * a <code>Calendar</code> object, the driver can calculate the time
     * taking into account a custom timezone and locale.  If no
     * <code>Calendar</code> object is specified, the driver uses the default
     * timezone and locale.
     *
     * @param parameterIndex the first parameter is 1, the second is 2, ...
     * @param x the parameter value
     * @param cal the <code>Calendar</code> object the driver will use
     *            to construct the time
     * @exception SQLException if a database access error occurs
     */
    public void setTime(int parameterIndex,
                        java.sql.Time x,
                        Calendar cal)
        throws SQLException
    {
       if(cal==null) {
          cal=Calendar.getInstance();
       }
       Object arg = this.findColInfo (parameterIndex).transTimeForInput (x, cal);
       this.outputArgs [parameterIndex - 1] = arg;
    }

    /**
     * setTimestamp method comment.
     */
    public void setTimestamp(
        int parameterIndex,
        java.sql.Timestamp x)
    throws java.sql.SQLException
    {
        this.setTimestamp(parameterIndex,x,null);
    }
    /**
     * JDBC 2.0
     *
     * Sets the designated parameter to a java.sql.Timestamp value,
     * using the given <code>Calendar</code> object.  The driver uses
     * the <code>Calendar</code> object to construct an SQL TIMESTAMP,
     * which the driver then sends to the database.  With a
     * a <code>Calendar</code> object, the driver can calculate the timestamp
     * taking into account a custom timezone and locale.  If no
     * <code>Calendar</code> object is specified, the driver uses the default
     * timezone and locale.
     *
     * @param parameterIndex the first parameter is 1, the second is 2, ...
     * @param x the parameter value
     * @param cal the <code>Calendar</code> object the driver will use
     *            to construct the timestamp
     * @exception SQLException if a database access error occurs
     */
    public void setTimestamp(int parameterIndex,
                             java.sql.Timestamp x,
                             Calendar cal)
        throws SQLException
    {
        if(cal==null) {
           cal=Calendar.getInstance();
        }
        Object arg = this.findColInfo (parameterIndex).transTimestampForInput (x, cal);
        this.outputArgs [parameterIndex - 1] = arg;
    }

    /**
     *
     */
    public void addWarning (SQLWarning warning) 
    {
    }
    /**
     *
     * @return java.sql.Connection
     */
    public com.sap.dbtech.jdbc.ConnectionSapDB getConnectionSapDB ()
    {
        return null;
    }
    /**
     *
     * @return StructuredMem
     */
    public com.sap.dbtech.util.StructuredMem getReplyData ()
        throws SQLException
    {
        return this.dataMem;
    }

    /**
     *
     * @param wasNull boolean
     */
    public void setLastWasNull (boolean wasNull)
    {
        this.lastWasNull = wasNull;
    }
    /**
     *
     * @return boolean
     */
    public boolean wasNull() 
    throws SQLException
    {
        return this.lastWasNull;
    }

	public AbstractABAPStreamGetval getOMSGetval(int i) throws SQLException {
		return null;
	}
}
