package com.wecise.odb.jdbc;

import com.wecise.odb.Error;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Map;

public class ODBResultSet implements ResultSet {
    private ArrayList data;
    private Map meta;
    private int rowIndex;
    private ODBStatement statement;

    private ResultSetMetaData resultSetMetaData;

    ODBResultSet(ArrayList data, Map meta, ODBStatement statement) {
        this.data = data;
        this.meta = meta;
        this.rowIndex = 0;
        this.statement = statement;
    }

    ODBResultSet() {

    }

    @Override
    public boolean next() throws SQLException {
        if (data.size() > 0 && this.rowIndex != data.size()) {
            this.rowIndex++;
            return true;
        }
        return false;
    }

    @Override
    public void close() throws SQLException {

    }

    @Override
    public boolean wasNull() throws SQLException {
        if (rowIndex >= 1) {
            return data.get(rowIndex - 1) == null;
        } else {
            throw new SQLException(Error.noGetMethod);
        }
    }

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

    @Override
    public String getString(int i) throws SQLException {
        Object o = getObject(i);
        if (o != null) {
            return o.toString();
        }
        return null;
    }

    @Override
    public boolean getBoolean(int i) throws SQLException {
        Object o = getObject(i);
        if (o != null) {
            return Boolean.parseBoolean(o.toString());
        }
        return false;
    }

    @Override
    public byte getByte(int i) throws SQLException {
        Object o = getObject(i);
        if (o != null) {
            return Byte.parseByte(o.toString());
        }
        return 0;
    }

    @Override
    public short getShort(int i) throws SQLException {
        Object o = getObject(i);
        if (o != null) {
            String s = o.toString();
            if (s.contains(".")) {
                s = s.substring(0, s.indexOf("."));
            }
            return Short.parseShort(s);
        }
        return 0;
    }

    @Override
    public int getInt(int i) throws SQLException {
        Object o = getObject(i);
        if (o != null) {
            String s = o.toString();
            if (s.contains(".")) {
                s = s.substring(0, s.indexOf("."));
            }
            return Integer.parseInt(s);
        }
        return 0;
    }

    @Override
    public long getLong(int i) throws SQLException {
        Object o = getObject(i);
        if (o != null) {
            String s = o.toString();
            if (s.contains(".")) {
                s = s.substring(0, s.indexOf("."));
            }
            return Long.parseLong(s);
        }
        return 0;
    }

    @Override
    public float getFloat(int i) throws SQLException {
        Object o = getObject(i);
        if (o != null) {
            return Float.parseFloat(o.toString());
        }
        return 0;
    }

    @Override
    public double getDouble(int i) throws SQLException {
        Object o = getObject(i);
        if (o != null) {
            return Double.parseDouble(o.toString());
        }
        return 0;
    }

    @Override
    public BigDecimal getBigDecimal(int i, int i1) throws SQLException {
        // let getBigDecimal(int) handle this for now
        return getBigDecimal(i);
    }

    @Override
    public byte[] getBytes(int i) throws SQLException {
        Object o = getObject(i);
        if (o != null) {
            return o.toString().getBytes();
        }
        return new byte[0];
    }

    @Override
    public Date getDate(int i) throws SQLException {
        Object o = getObject(i);
        if (o != null) {
            try {
                String s = o.toString();
                if (o.toString().length() < 24) {
                    int msIdx = s.lastIndexOf(".");
                    if (msIdx == -1) {
                        s = s.substring(0, s.length() - 1) + ".000Z";
                    } else {
                        String ms = s.substring(msIdx + 1, s.length() - 1);
                        for (int k = 0; k < 3 - ms.length(); k ++) {
                            ms += "0";
                        }
                        s = s.substring(0, msIdx + 1) + ms + "Z";
                    }
                }
                return new Date(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(s).getTime()); //  RFC3339
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public Time getTime(int i) throws SQLException {
        Object o = getObject(i);
        if (o != null) {
            long timestamp = Long.parseLong(o.toString());
            return new Time(timestamp);
        }
        return null;
    }

    @Override
    public Timestamp getTimestamp(int i) throws SQLException {
        Object o = getObject(i);
        if (o != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); // RFC3339
            try {
                long timestamp = sdf.parse(o.toString()).getTime();
                return new Timestamp(timestamp);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public InputStream getAsciiStream(int i) throws SQLException {
        Object o = getObject(i);
        if (o != null) {
            return (o.toString() == null) ? null : new ByteArrayInputStream(o.toString().getBytes());
        }
        return null;
    }

    @Override
    public InputStream getUnicodeStream(int i) throws SQLException {
        return getAsciiStream(i);
    }

    @Override
    public InputStream getBinaryStream(int i) throws SQLException {
        return getAsciiStream(i);
    }

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

    @Override
    public String getString(String s) throws SQLException {
        Object o = getObject(s);
        if (o != null) {
            return o.toString();
        }
        return null;
    }

    @Override
    public boolean getBoolean(String s) throws SQLException {
        Object o = getObject(s);
        if (o != null) {
            return Boolean.parseBoolean(o.toString());
        }
        return false;
    }

    @Override
    public byte getByte(String s) throws SQLException {
        Object o = getObject(s);
        if (o != null) {
            return Byte.parseByte(o.toString());
        }
        return 0;
    }

    @Override
    public short getShort(String s) throws SQLException {
        Object o = getObject(s);
        if (o != null) {
            String v = o.toString();
            if (v.contains(".")) {
                v = v.substring(0, v.indexOf("."));
            }
            return Short.parseShort(v);
        }
        return 0;
    }

    @Override
    public int getInt(String s) throws SQLException {
        Object o = getObject(s);
        if (o != null) {
            String v = o.toString();
            if (v.contains(".")) {
                v = v.substring(0, v.indexOf("."));
            }
            return Integer.parseInt(v);
        }
        return 0;
    }

    @Override
    public long getLong(String s) throws SQLException {
        Object o = getObject(s);
        if (o != null) {
            String v = o.toString();
            if (v.contains(".")) {
                v = v.substring(0, v.indexOf("."));
            }
            return Long.parseLong(v);
        }
        return 0;
    }

    @Override
    public float getFloat(String s) throws SQLException {
        Object o = getObject(s);
        if (o != null) {
            return Float.parseFloat(o.toString());
        }
        return 0;
    }

    @Override
    public double getDouble(String s) throws SQLException {
        Object o = getObject(s);
        if (o != null) {
            return Double.parseDouble(o.toString());
        }
        return 0;
    }

    @Override
    public BigDecimal getBigDecimal(String s, int i) throws SQLException {
        return getBigDecimal(s);
    }

    @Override
    public byte[] getBytes(String s) throws SQLException {
        Object o = getObject(s);
        if (o != null) {
            return o.toString().getBytes();
        }
        return new byte[0];
    }

    @Override
    public Date getDate(String s) throws SQLException {
        Object o = getObject(s);
        if (o != null) {
            try {
                String ds = o.toString();
                if (o.toString().length() < 24) {
                    int msIdx = ds.lastIndexOf(".");
                    if (msIdx == -1) {
                        ds = ds.substring(0, ds.length() - 1) + ".000Z";
                    } else {
                        String ms = ds.substring(msIdx + 1, ds.length() - 1);
                        for (int k = 0; k < 3 - ms.length(); k ++) {
                            ms += "0";
                        }
                        ds = ds.substring(0, msIdx + 1) + ms + "Z";
                    }
                }
                return new Date(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(ds).getTime()); //  RFC3339
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public Time getTime(String s) throws SQLException {
        Object o = getObject(s);
        if (o != null) {
            long timestamp = Long.parseLong(o.toString());
            return new Time(timestamp);
        }
        return null;
    }

    @Override
    public Timestamp getTimestamp(String s) throws SQLException {
        Object o = getObject(s);
        if (o != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); // RFC3339
            try {
                long timestamp = sdf.parse(o.toString()).getTime();
                return new Timestamp(timestamp);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public InputStream getAsciiStream(String s) throws SQLException {
        Object o = getObject(s);
        if (o != null) {
            return (o.toString() == null) ? null : new ByteArrayInputStream(o.toString().getBytes());
        }
        return null;
    }

    @Override
    public InputStream getUnicodeStream(String s) throws SQLException {
        return getAsciiStream(s);
    }

    @Override
    public InputStream getBinaryStream(String s) throws SQLException {
        return getAsciiStream(s);
    }

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


    @Override
    public SQLWarning getWarnings() throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getWarnings()");
//        return null;
    }

    @Override
    public void clearWarnings() throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.clearWarnings()");
    }

    @Override
    public String getCursorName() throws SQLException {
       throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getCursorName()");
    }

    @Override
    public ResultSetMetaData getMetaData() throws SQLException {
        if (this.resultSetMetaData == null) {
            Map classes = (Map) this.meta.get("classes");
            if (classes != null && classes.keySet().size() > 0) {
                Object[] names = classes.keySet().toArray();
                String tableName = names[0].toString(); // First class is table name
                String[] columnNames = null;
                String[] columnLabels = null;
                String[] columnTypes = null;
                int[] columnDisplaySizes = null;
                Map columns = (Map) this.meta.get("columns");
                if (columns != null && columns.keySet().size() > 0) {
                    ArrayList cols = (ArrayList) columns.get(tableName);
                    if (cols != null && cols.size() > 0) {
                        columnNames = new String[cols.size()];
                        columnLabels = new String[cols.size()];
                        columnTypes = new String[cols.size()];
                        columnDisplaySizes = new int[cols.size()];
                        for (int i = 0;i < cols.size();i++) {
                            Map col = (Map) cols.get(i);
                            columnNames[i] = col.get("name").toString();
                            columnLabels[i] = col.get("label").toString();
                            columnTypes[i] = col.get("type").toString();
                            columnDisplaySizes[i] = 20; // 指示指定列的最大标准宽度，以字符为单位
                        }
                    }
                }
                this.resultSetMetaData = new ODBResultSetMetaData(tableName, columnNames, columnLabels, columnTypes, columnDisplaySizes);
            }
        }
        return this.resultSetMetaData;
    }

    @Override
    public Object getObject(int i) throws SQLException {
        ResultSetMetaData meta = this.getMetaData();
        String columnName = meta.getColumnName(i);
        return ((Map) this.data.get(rowIndex - 1)).get(columnName);
    }

    @Override
    public Object getObject(String s) throws SQLException {
        return ((Map) this.data.get(rowIndex - 1)).get(s.toLowerCase());
    }

    @Override
    public int findColumn(String s) throws SQLException {
        ResultSetMetaData meta = this.getMetaData();
        for (int i = 1; i <= meta.getColumnCount(); i++) {
            if (s.equals(meta.getColumnLabel(i))) {
                return i;
            }
        }
        return 0;
    }

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

    //---------------------------------------------------------------------
    // Getters and Setters
    //---------------------------------------------------------------------

    @Override
    public Reader getCharacterStream(int i) throws SQLException {
        String str = getString(i);
        return (str == null) ? null : new StringReader(str);
    }

    @Override
    public Reader getCharacterStream(String s) throws SQLException {
        String str = getString(s);
        return (str == null) ? null : new StringReader(str);
    }

    @Override
    public BigDecimal getBigDecimal(int i) throws SQLException {
        BigDecimal retval = null;
        Object o = getObject(i);
        if (o != null) {
            try {
                retval = new BigDecimal(o.toString());
            } catch (NumberFormatException e) {
                throw new SQLException(Error.cannotConvertToBigDecimal + ": " + o.toString());
            }
        }
        return retval;
    }

    @Override
    public BigDecimal getBigDecimal(String s) throws SQLException {
        BigDecimal retval = null;
        Object o = getObject(s);
        if (o != null) {
            try {
                retval = new BigDecimal(o.toString());
            } catch (NumberFormatException e) {
                throw new SQLException(Error.cannotConvertToBigDecimal + ": " + o.toString());
            }
        }
        return retval;
    }

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

    @Override
    public boolean isBeforeFirst() throws SQLException {
        return this.rowIndex == 0;
    }

    @Override
    public boolean isAfterLast() throws SQLException {
        return this.rowIndex == this.data.size() + 1;
    }

    @Override
    public boolean isFirst() throws SQLException {
        return this.rowIndex == 1;
    }

    @Override
    public boolean isLast() throws SQLException {
        return this.rowIndex == this.data.size();
    }

    @Override
    public void beforeFirst() throws SQLException {
        this.rowIndex = 0;
    }

    @Override
    public void afterLast() throws SQLException {
        if (this.data.size() > 0) {
            this.rowIndex = this.data.size() + 1;
        }
    }

    @Override
    public boolean first() throws SQLException {
        if (this.data.size() > 0) {
            this.rowIndex = 1;
            return true;
        }
        return false;
    }

    @Override
    public boolean last() throws SQLException {
        if (this.data.size() > 0) {
            this.rowIndex = this.data.size();
            return true;
        }
        return false;
    }

    @Override
    public int getRow() throws SQLException {
        return this.rowIndex;
    }

    @Override
    public boolean absolute(int i) throws SQLException {
        if (this.data.size() > 0) {
            if (i > 0) {
                first();
            } else {
                last();
            }
            this.rowIndex += i;
            return true;
        }
        return false;
    }

    @Override
    public boolean relative(int i) throws SQLException {
        if (this.data.size() > 0) {
            if (i > 0 && this.rowIndex + i < this.data.size()) {
                this.rowIndex += i;
                return true;
            }
            if (i < 0 && this.rowIndex + i >= 0) {
                this.rowIndex += i;
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean previous() throws SQLException {
        if (this.data.size() > 0) {
            if (this.rowIndex > 1) {
                this.rowIndex--;
                return true;
            }
        }
        return false;
    }

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

    @Override
    public void setFetchDirection(int i) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.unsupportedDirection + ": ResultSet.setFetchDirection()");
    }

    @Override
    public int getFetchDirection() throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.unsupportedDirection + ": ResultSet.getFetchDirection()");
//        return 0;
    }

    @Override
    public void setFetchSize(int i) throws SQLException {

    }

    @Override
    public int getFetchSize() throws SQLException {
        return this.data.size();
    }

    @Override
    public int getType() throws SQLException {
        return ResultSet.TYPE_FORWARD_ONLY;
    }

    @Override
    public int getConcurrency() throws SQLException {
        return ResultSet.CONCUR_READ_ONLY;
    }

    @Override
    public boolean rowUpdated() throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.rowUpdated()");
//        return false;
    }

    @Override
    public boolean rowInserted() throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.rowInserted()");
//        return false;
    }

    @Override
    public boolean rowDeleted() throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.rowDeleted()");
//        return false;
    }

    @Override
    public void updateNull(int i) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateNull(int)");
    }

    @Override
    public void updateBoolean(int i, boolean b) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBoolean(int, boolean)");
    }

    @Override
    public void updateByte(int i, byte b) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateByte(int, byte)");
    }

    @Override
    public void updateShort(int i, short i1) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateShort(int, short)");
    }

    @Override
    public void updateInt(int i, int i1) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateInt(int, int)");
    }

    @Override
    public void updateLong(int i, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateLong(int, long)");
    }

    @Override
    public void updateFloat(int i, float v) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateFloat(int, float)");
    }

    @Override
    public void updateDouble(int i, double v) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateDouble(int, double)");
    }

    @Override
    public void updateBigDecimal(int i, BigDecimal bigDecimal) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBigDecimal(int, BigDecimal)");
    }

    @Override
    public void updateString(int i, String s) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateString(int, String)");
    }

    @Override
    public void updateBytes(int i, byte[] bytes) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBytes(int, byte[])");
    }

    @Override
    public void updateDate(int i, Date date) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateDate(int, Date)");
    }

    @Override
    public void updateTime(int i, Time time) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateTime(int, Time)");
    }

    @Override
    public void updateTimestamp(int i, Timestamp timestamp) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateTimestamp(int, Timestamp)");
    }

    @Override
    public void updateAsciiStream(int i, InputStream inputStream, int i1) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateAsciiStream(int, InputStream, int)");
    }

    @Override
    public void updateBinaryStream(int i, InputStream inputStream, int i1) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBinaryStream(int, InputStream, int)");
    }

    @Override
    public void updateCharacterStream(int i, Reader reader, int i1) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateCharacterStream(int, Reader, int)");
    }

    @Override
    public void updateObject(int i, Object o, int i1) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateObject(int, Object, int)");
    }

    @Override
    public void updateObject(int i, Object o) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateObject(int, Object)");
    }

    @Override
    public void updateNull(String s) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateNull(String)");
    }

    @Override
    public void updateBoolean(String s, boolean b) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBoolean(String, boolean)");
    }

    @Override
    public void updateByte(String s, byte b) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateByte(String, byte)");
    }

    @Override
    public void updateShort(String s, short i) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateShort(String, short)");
    }

    @Override
    public void updateInt(String s, int i) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateInt(String, int)");
    }

    @Override
    public void updateLong(String s, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateLong(String, long)");
    }

    @Override
    public void updateFloat(String s, float v) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateFloat(String, float)");
    }

    @Override
    public void updateDouble(String s, double v) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateDouble(String, double)");
    }

    @Override
    public void updateBigDecimal(String s, BigDecimal bigDecimal) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBigDecimal(String, BigDecimal)");
    }

    @Override
    public void updateString(String s, String s1) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateString(String, String)");
    }

    @Override
    public void updateBytes(String s, byte[] bytes) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBytes(String, byte[])");
    }

    @Override
    public void updateDate(String s, Date date) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateDate(String, Date)");
    }

    @Override
    public void updateTime(String s, Time time) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateTime(String, Time)");
    }

    @Override
    public void updateTimestamp(String s, Timestamp timestamp) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateTimestamp(String, Timestamp)");
    }

    @Override
    public void updateAsciiStream(String s, InputStream inputStream, int i) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateAsciiStream(String, InputStream, int)");
    }

    @Override
    public void updateBinaryStream(String s, InputStream inputStream, int i) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBinaryStream(String, InputStream, int)");
    }

    @Override
    public void updateCharacterStream(String s, Reader reader, int i) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateCharacterStream(String, InputStream, int)");
    }

    @Override
    public void updateObject(String s, Object o, int i) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateObject(String, Object, int)");
    }

    @Override
    public void updateObject(String s, Object o) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateObject(String, Object)");
    }

    @Override
    public void insertRow() throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.insertRow()");
    }

    @Override
    public void updateRow() throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateRow()");
    }

    @Override
    public void deleteRow() throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.deleteRow()");
    }

    @Override
    public void refreshRow() throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.refreshRow()");
    }

    @Override
    public void cancelRowUpdates() throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.cancelRowUpdates()");
    }

    @Override
    public void moveToInsertRow() throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.moveToInsertRow()");
    }

    @Override
    public void moveToCurrentRow() throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.moveToCurrentRow()");
    }

    @Override
    public Statement getStatement() throws SQLException {
        return this.statement;
    }

    @Override
    public Object getObject(int i, Map<String, Class<?>> map) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getObject(int, Map)");
//        return null;
    }

    @Override
    public Ref getRef(int i) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getRef(int)");
//        return null;
    }

    @Override
    public Blob getBlob(int i) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getBlob(int)");
//        return null;
    }

    @Override
    public Clob getClob(int i) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getClob(int)");
//        return null;
    }

    @Override
    public Array getArray(int i) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getArray(int)");
//        return null;
    }

    @Override
    public Object getObject(String s, Map<String, Class<?>> map) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getObject(String, Map)");
//        return null;
    }

    @Override
    public Ref getRef(String s) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getRef(String)");
//        return null;
    }

    @Override
    public Blob getBlob(String s) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getBlob(String)");
//        return null;
    }

    @Override
    public Clob getClob(String s) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getClob(String)");
//        return null;
    }

    @Override
    public Array getArray(String s) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getArray(String)");
//        return null;
    }

    @Override
    public Date getDate(int i, Calendar calendar) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getDate(int, Calendar)");
//        return null;
    }

    @Override
    public Date getDate(String s, Calendar calendar) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getDate(String, Calendar)");
//        return null;
    }

    @Override
    public Time getTime(int i, Calendar calendar) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getTime(int, Calendar)");
//        return null;
    }

    @Override
    public Time getTime(String s, Calendar calendar) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getTime(String, Calendar)");
//        return null;
    }

    @Override
    public Timestamp getTimestamp(int i, Calendar calendar) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getTimestamp(int, Calendar)");
//        return null;
    }

    @Override
    public Timestamp getTimestamp(String s, Calendar calendar) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getTimestamp(String, Calendar)");
//        return null;
    }

    @Override
    public URL getURL(int i) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getURL(int)");
//        return null;
    }

    @Override
    public URL getURL(String s) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getURL(String)");
//        return null;
    }

    @Override
    public void updateRef(int i, Ref ref) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateRef(int, Ref)");
    }

    @Override
    public void updateRef(String s, Ref ref) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateRef(String, Ref)");
    }

    @Override
    public void updateBlob(int i, Blob blob) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBlob(int, Blob)");
    }

    @Override
    public void updateBlob(String s, Blob blob) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBlob(String, Blob)");
    }

    @Override
    public void updateClob(int i, Clob clob) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateClob(int, Clob)");
    }

    @Override
    public void updateClob(String s, Clob clob) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateClob(String, Clob)");
    }

    @Override
    public void updateArray(int i, Array array) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateArray(int, Array)");
    }

    @Override
    public void updateArray(String s, Array array) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateArray(String, Array)");
    }

    @Override
    public RowId getRowId(int i) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getRowId(int)");
//        return null;
    }

    @Override
    public RowId getRowId(String s) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.getRowId(String)");
//        return null;
    }

    @Override
    public void updateRowId(int i, RowId rowId) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateRowId(int, RowId)");
    }

    @Override
    public void updateRowId(String s, RowId rowId) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateRowId(String, RowId)");
    }

    @Override
    public int getHoldability() throws SQLException {
        return 0;
    }

    @Override
    public boolean isClosed() throws SQLException {
        return false;
    }

    @Override
    public void updateNString(int i, String s) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateNString(int, String)");
    }

    @Override
    public void updateNString(String s, String s1) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateNString(String, String)");
    }

    @Override
    public void updateNClob(int i, NClob nClob) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateNClob(int, NClob)");
    }

    @Override
    public void updateNClob(String s, NClob nClob) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateNClob(String, NClob)");
    }

    @Override
    public NClob getNClob(int i) throws SQLException {
        return null;
    }

    @Override
    public NClob getNClob(String s) throws SQLException {
        return null;
    }

    @Override
    public SQLXML getSQLXML(int i) throws SQLException {
        return null;
    }

    @Override
    public SQLXML getSQLXML(String s) throws SQLException {
        return null;
    }

    @Override
    public void updateSQLXML(int i, SQLXML sqlxml) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateSQLXML(int, SQLXML)");
    }

    @Override
    public void updateSQLXML(String s, SQLXML sqlxml) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateSQLXML(String, SQLXML)");
    }

    @Override
    public String getNString(int i) throws SQLException {
        return null;
    }

    @Override
    public String getNString(String s) throws SQLException {
        return null;
    }

    @Override
    public Reader getNCharacterStream(int i) throws SQLException {
        return null;
    }

    @Override
    public Reader getNCharacterStream(String s) throws SQLException {
        return null;
    }

    @Override
    public void updateNCharacterStream(int i, Reader reader, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateNCharacterStream(String, Reader, long)");
    }

    @Override
    public void updateNCharacterStream(String s, Reader reader, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateNCharacterStream(String, Reader, long)");
    }

    @Override
    public void updateAsciiStream(int i, InputStream inputStream, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateAsciiStream(String, InputStream, long)");
    }

    @Override
    public void updateBinaryStream(int i, InputStream inputStream, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBinaryStream(int, InputStream, long)");
    }

    @Override
    public void updateCharacterStream(int i, Reader reader, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateCharacterStream(int, Reader, long)");
    }

    @Override
    public void updateAsciiStream(String s, InputStream inputStream, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateAsciiStream(String, InputStream, long)");
    }

    @Override
    public void updateBinaryStream(String s, InputStream inputStream, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBinaryStream(String, InputStream, long)");
    }

    @Override
    public void updateCharacterStream(String s, Reader reader, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateCharacterStream(String, Reader, long)");
    }

    @Override
    public void updateBlob(int i, InputStream inputStream, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBlob(int, InputStream, long)");
    }

    @Override
    public void updateBlob(String s, InputStream inputStream, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBlob(String, InputStream, long)");
    }

    @Override
    public void updateClob(int i, Reader reader, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateClob(int, Reader, long)");
    }

    @Override
    public void updateClob(String s, Reader reader, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateClob(String, Reader, long)");
    }

    @Override
    public void updateNClob(int i, Reader reader, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateNClob(int, Reader, long)");
    }

    @Override
    public void updateNClob(String s, Reader reader, long l) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateNClob(String, Reader, long)");
    }

    @Override
    public void updateNCharacterStream(int i, Reader reader) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateNCharacterStream(int, Reader, long)");
    }

    @Override
    public void updateNCharacterStream(String s, Reader reader) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateNCharacterStream(String, Reader)");
    }

    @Override
    public void updateAsciiStream(int i, InputStream inputStream) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateAsciiStream(int, Reader)");
    }

    @Override
    public void updateBinaryStream(int i, InputStream inputStream) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBinaryStream(int, Reader)");
    }

    @Override
    public void updateCharacterStream(int i, Reader reader) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateCharacterStream(int, Reader)");
    }

    @Override
    public void updateAsciiStream(String s, InputStream inputStream) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateAsciiStream(String, Reader)");
    }

    @Override
    public void updateBinaryStream(String s, InputStream inputStream) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBinaryStream(String, Reader)");
    }

    @Override
    public void updateCharacterStream(String s, Reader reader) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateCharacterStream(String, Reader)");
    }

    @Override
    public void updateBlob(int i, InputStream inputStream) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBlob(int, InputStream)");
    }

    @Override
    public void updateBlob(String s, InputStream inputStream) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateBlob(String, InputStream)");
    }

    @Override
    public void updateClob(int i, Reader reader) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateClob(int, Reader)");
    }

    @Override
    public void updateClob(String s, Reader reader) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateClob(String, Reader)");
    }

    @Override
    public void updateNClob(int i, Reader reader) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateNClob(int, Reader)");
    }

    @Override
    public void updateNClob(String s, Reader reader) throws SQLException {
        throw new SQLFeatureNotSupportedException(Error.methodNotSupported + ": ResultSet.updateNClob(String, Reader)");
    }

    @Override
    public <T> T getObject(int i, Class<T> aClass) throws SQLException {
        return null;
    }

    @Override
    public <T> T getObject(String s, Class<T> aClass) throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> aClass) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> aClass) throws SQLException {
        return false;
    }
}
