/*
 * Copyright (C) 2001 eZiba.com, Inc.
 * All Rights Reserved
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *    Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *    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.  Neither the name of eZiba.com nor the
 *    names of its contributors may be used to endorse or promote
 *    products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS 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
 * eZiba.com OR CONTRIBUTORS 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 com.mockobjects.eziba.sql;
import java.sql.SQLException;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Map;
import java.util.HashMap;public class ResultSet
  implements java.sql.ResultSet
{

    public static final ResultSet EMPTY_SET = new ResultSet();

    private ResultSet()
    {
        this (null, new Object[0], null);
    }


    private int m_current;
    private boolean m_wasNull = false;

    public ResultSet(Object [] p_data, String [] p_names)
    {
        this(p_data, p_names, p_names);
    }

    /**
     * Factor these validations out since you can't insert assertions
     * before a call to super() or this().
     */

    private static Object [] validateConstructorArgs(Object [] p_data,
                                                     String [] p_columnNames,
                                                     String [] p_propNames)
    {
        if (p_data == null)
        {
            throw new IllegalArgumentException("Object array can't be null");
        }
        if (p_columnNames == null)
        {
            throw new IllegalArgumentException("Column names can't be null");
        }
        if (p_propNames == null)
        {
            throw new IllegalArgumentException("Property names can't be null");
        }
        if (p_columnNames.length != p_propNames.length)
        {
            throw new IllegalArgumentException("Number of column names ("
                                               + p_columnNames.length + ")"
                                               + " does not match "
                                               + " number of property names ("
                                               + p_propNames.length + ")");
        }
        return p_data;
    }

    public ResultSet(Object [] p_data,
                     String [] p_columnNames,
                     String [] p_propNames)
    {
        this (new ReflectiveResultSetRowGenerator(p_propNames),
              validateConstructorArgs(p_data, p_columnNames, p_propNames),
              createMapFromStringArray(p_columnNames));
    }

    private static Map createMapFromStringArray(String [] p_columnNames)
    {
        Map map = new HashMap();
        for (int i = 0; i < p_columnNames.length; ++i)
        {
            map.put(p_columnNames[i],new Integer(i));
        }
        return map;
    }

    public ResultSet(ResultSetRowGenerator p_generator,
                     Object [] p_data,
                     Map p_columnNameMap)
    {
        m_generator = p_generator;
        m_data = p_data;
        m_columnNameMap = p_columnNameMap;
        m_current = -1;
    }

    private final ResultSetRowGenerator m_generator;
    private final Object [] m_data;
    private final Map m_columnNameMap;

    private Object [] getCurrentRow()
        throws SQLException
    {
        Object [] result = m_generator.createRow(m_data[m_current]);
        // FIXME:
        //  assert result != null
        //  assert result.length == m_columnNameMap.size()
        return result;
    }

    private Object getColumnData(int p_columnNum)
        throws SQLException
    {
        Object [] row = getCurrentRow();
        if (p_columnNum < 0 || p_columnNum >= row.length)
        {
            throw new SQLException("Illegal column number " + p_columnNum);
        }
        // FIXME: assert that p_columnNum is one of the values in
        //    m_columnNameMap

        Object result = row[p_columnNum];

        m_wasNull = (result == null);

        return result;
    }

      public int findColumn(String p_columnName)
          throws SQLException
      {
          Integer i = (Integer) m_columnNameMap.get(p_columnName);
          if (i != null)
          {
              return i.intValue();
          }
          else
          {
              throw new SQLException("No such column " + p_columnName);
          }
    }

    public boolean next()
        throws SQLException
    {
        m_current++;
        return m_current < m_data.length;
    }

    public void close()
        throws SQLException
    {
        // noop
    }

    public boolean wasNull()
        throws SQLException
    {
        return m_wasNull;
    }

    public String getString(int columnIndex)
        throws SQLException
    {
        return (String) getColumnData(columnIndex);
    }

    public boolean getBoolean(int columnIndex)
        throws SQLException
    {
        return ((Boolean) getColumnData(columnIndex)).booleanValue();
    }

    public byte getByte(int columnIndex)
        throws SQLException
    {
        return ((Byte) getColumnData(columnIndex)).byteValue();
    }

    public short getShort(int columnIndex)
        throws SQLException
    {
        return ((Short) getColumnData(columnIndex)).shortValue();
    }

    public int getInt(int columnIndex)
        throws SQLException
    {
        Integer i = (Integer) getColumnData(columnIndex);
        return i == null ? 0 : i.intValue();
    }

    public long getLong(int columnIndex)
        throws SQLException
    {
        return ((Long) getColumnData(columnIndex)).longValue();
    }

    public float getFloat(int columnIndex)
        throws SQLException
    {
        return ((Float) getColumnData(columnIndex)).floatValue();
    }

    public double getDouble(int columnIndex)
        throws SQLException
    {
        return ((Double) getColumnData(columnIndex)).doubleValue();
    }

    /**
     * @deprecated
     */
    public BigDecimal getBigDecimal(int columnIndex, int scale)
        throws SQLException
    {
        return (BigDecimal) getColumnData(columnIndex);
    }

    public byte[] getBytes(int columnIndex)
        throws SQLException
    {
        return (byte []) getColumnData(columnIndex);
    }

    public java.sql.Date getDate(int columnIndex)
        throws SQLException
    {
        // be forgiving about java.util vs java.sql Dates
        Object o = getColumnData(columnIndex);
        if (o == null)
        {
            return null;
        }
        else if (o instanceof java.sql.Date)
        {
            return (java.sql.Date) o;
        }
        else if (o instanceof java.util.Date)
        {
            return new java.sql.Date(((java.util.Date)o).getTime());
        }
        else
        {
            throw new SQLException("Expected date type, got " + o.getClass());
        }
    }

    public java.sql.Time getTime(int columnIndex)
        throws SQLException
    {
        return (java.sql.Time) getColumnData(columnIndex);
    }

    public java.sql.Timestamp getTimestamp(int columnIndex)
        throws SQLException
    {
        return (java.sql.Timestamp) getColumnData(columnIndex);
    }

    public java.io.InputStream getAsciiStream(int columnIndex)
        throws SQLException
    {
        return (java.io.InputStream) getColumnData(columnIndex);
    }

    /**
     * @deprecated
     */
    public java.io.InputStream getUnicodeStream(int columnIndex)
        throws SQLException
    {
        return (java.io.InputStream) getColumnData(columnIndex);
    }

    public java.io.InputStream getBinaryStream(int columnIndex)

        throws SQLException
    {
        return (java.io.InputStream) getColumnData(columnIndex);
    }

    //======================================================================
    // Methods for accessing results by column name
    //======================================================================

    public String getString(String columnName)
        throws SQLException
    {
        return getString(findColumn(columnName));
    }

    public boolean getBoolean(String columnName)
        throws SQLException
    {
        return getBoolean(findColumn(columnName));
    }

    public byte getByte(String columnName)
        throws SQLException
    {
        return getByte(findColumn(columnName));
    }

    public short getShort(String columnName)
        throws SQLException
    {
        return getShort(findColumn(columnName));
    }

    public int getInt(String columnName)
        throws SQLException
    {
        return getInt(findColumn(columnName));
    }

    public long getLong(String columnName)
        throws SQLException
    {
        return getLong(findColumn(columnName));
    }

    public float getFloat(String columnName)
        throws SQLException
    {
        return getFloat(findColumn(columnName));
    }

    public double getDouble(String columnName)
        throws SQLException
    {
        return getDouble(findColumn(columnName));
    }

    /**
     * @deprecated
     */
    public BigDecimal getBigDecimal(String columnName, int scale)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public byte[] getBytes(String columnName)
        throws SQLException
    {
        return getBytes(findColumn(columnName));
    }

    public java.sql.Date getDate(String columnName)
        throws SQLException
    {
        return getDate(findColumn(columnName));
    }

    public java.sql.Time getTime(String columnName)
        throws SQLException
    {
        return getTime(findColumn(columnName));
    }

    public java.sql.Timestamp getTimestamp(String columnName)
        throws SQLException
    {
        return getTimestamp(findColumn(columnName));
    }

    public java.io.InputStream getAsciiStream(String columnName)
        throws SQLException
    {
        return getAsciiStream(findColumn(columnName));
    }

    /**
     * @deprecated
     */
    public java.io.InputStream getUnicodeStream(String columnName)
        throws SQLException
    {
        return getUnicodeStream(findColumn(columnName));
    }

    public java.io.InputStream getBinaryStream(String columnName)

        throws SQLException
    {
        return getBinaryStream(findColumn(columnName));
    }

    public BigDecimal getBigDecimal(String columnName)
        throws SQLException
    {
        return (BigDecimal) getColumnData(findColumn(columnName));
    }

    public boolean first()
        throws SQLException
    {
        m_current = -1;
        return m_data.length > 0;
    }

    //=====================================================================
    // Advanced features:
    //=====================================================================

    public java.sql.SQLWarning getWarnings()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void clearWarnings()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public String getCursorName()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.ResultSetMetaData getMetaData()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public Object getObject(int columnIndex)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public Object getObject(String columnName)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    //----------------------------------------------------------------



    //--------------------------JDBC 2.0-----------------------------------

    //---------------------------------------------------------------------
    // Getter's and Setter's
    //---------------------------------------------------------------------

    public java.io.Reader getCharacterStream(int columnIndex)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.io.Reader getCharacterStream(String columnName)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public BigDecimal getBigDecimal(int columnIndex)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    //---------------------------------------------------------------------
    // Traversal/Positioning
    //---------------------------------------------------------------------

    public boolean isBeforeFirst()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public boolean isAfterLast()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public boolean isFirst()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public boolean isLast()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void beforeFirst()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void afterLast()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public boolean last()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public int getRow()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public boolean absolute( int row )
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public boolean relative( int rows )
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public boolean previous()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    //---------------------------------------------------------------------
    // Properties
    //---------------------------------------------------------------------

    public void setFetchDirection(int direction)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public int getFetchDirection()
        throws SQLException
    {
        return FETCH_FORWARD;
    }

    public void setFetchSize(int rows)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public int getFetchSize()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public int getType()
        throws SQLException
    {
        return TYPE_FORWARD_ONLY;
    }

    public int getConcurrency()
        throws SQLException
    {
        return CONCUR_READ_ONLY;
    }

    //---------------------------------------------------------------------
    // Updates
    //---------------------------------------------------------------------

    public boolean rowUpdated()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public boolean rowInserted()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public boolean rowDeleted()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateNull(int columnIndex)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateBoolean(int columnIndex, boolean x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateByte(int columnIndex, byte x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateShort(int columnIndex, short x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateInt(int columnIndex, int x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateLong(int columnIndex, long x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateFloat(int columnIndex, float x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateDouble(int columnIndex, double x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateBigDecimal(int columnIndex, BigDecimal x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateString(int columnIndex, String x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateBytes(int columnIndex, byte x[])
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateDate(int columnIndex, java.sql.Date x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateTime(int columnIndex, java.sql.Time x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateTimestamp(int columnIndex, java.sql.Timestamp x)

        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateAsciiStream(int columnIndex,
                                  java.io.InputStream x,
                                  int length)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateBinaryStream(int columnIndex,
                                   java.io.InputStream x,
                                   int length)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateCharacterStream(int columnIndex,
                                      java.io.Reader x,
                                      int length)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateObject(int columnIndex, Object x, int scale)

        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateObject(int columnIndex, Object x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateNull(String columnName)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateBoolean(String columnName, boolean x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateByte(String columnName, byte x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateShort(String columnName, short x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateInt(String columnName, int x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateLong(String columnName, long x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateFloat(String columnName, float x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateDouble(String columnName, double x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateBigDecimal(String columnName, BigDecimal x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateString(String columnName, String x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateBytes(String columnName, byte x[])
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateDate(String columnName, java.sql.Date x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateTime(String columnName, java.sql.Time x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateTimestamp(String columnName, java.sql.Timestamp x)

        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateAsciiStream(String columnName,
                                  java.io.InputStream x,
                                  int length)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateBinaryStream(String columnName,
                                   java.io.InputStream x,
                                   int length)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateCharacterStream(String columnName,
                                      java.io.Reader reader,
                                      int length)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateObject(String columnName, Object x, int scale)

        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateObject(String columnName, Object x)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void insertRow()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void updateRow()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void deleteRow()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void refreshRow()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void cancelRowUpdates()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void moveToInsertRow()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public void moveToCurrentRow()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.Statement getStatement()
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public Object getObject(int i, java.util.Map map)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.Ref getRef(int i)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.Blob getBlob(int i)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.Clob getClob(int i)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.Array getArray(int i)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public Object getObject(String colName, java.util.Map map)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.Ref getRef(String colName)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.Blob getBlob(String colName)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.Clob getClob(String colName)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.Array getArray(String colName)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.Date getDate(int columnIndex, Calendar cal)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.Date getDate(String columnName, Calendar cal)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.Time getTime(int columnIndex, Calendar cal)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.Time getTime(String columnName, Calendar cal)
        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal)

        throws SQLException
    {
        throw new NotImplementedException();
    }

    public java.sql.Timestamp getTimestamp(String columnName, Calendar cal)

        throws SQLException
    {
        throw new NotImplementedException();
    }
}