Package GenericDBMS

Source Code of GenericDBMS.ResultSetHelper

/*
Copyright (c) 2003-2009 ITerative Consulting Pty Ltd. All Rights Reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:

o Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
 
o 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.
   
o This jcTOOL Helper Class software, whether in binary or source form may not be used within,
or to derive, any other product without the specific prior written permission of the copyright holder

 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "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 THE COPYRIGHT OWNER 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 GenericDBMS;

import java.math.BigDecimal;
import java.sql.Blob;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;

import Framework.BinaryData;
import Framework.BinaryNullable;
import Framework.BooleanData;
import Framework.BooleanNullable;
import Framework.DataValue;
import Framework.DateTimeData;
import Framework.DateTimeNullable;
import Framework.DecimalData;
import Framework.DecimalNullable;
import Framework.DoubleData;
import Framework.DoubleNullable;
import Framework.ErrorMgr;
import Framework.ImageData;
import Framework.ImageNullable;
import Framework.IntegerData;
import Framework.IntegerNullable;
import Framework.IntervalData;
import Framework.IntervalNullable;
import Framework.NumericData;
import Framework.StringUtils;
import Framework.TextData;
import Framework.TextNullable;
import Framework.UsageException;

/**
* This class provide Forte like semantics on a result set. This includes the following
* responsibilities:<p>
* <ul>
*   <li>Translating SQLExceptions into DataAccessExceptions via Spring</li>
*   <li>Providing methods to be able to read values into data value sub-classes, including
*     setting the NULL flag on nullable types when the type read from the database is null</li>
*   <li>Trimming spaces from the end of the text values returned. Note that Forte did not trim trailing
*     whitespaces in all cases, it seems to be only when the type of the column defined in the database
*     was of type CHAR. This logic is reproduced here.</li>
* </ul>
*
*/
public class ResultSetHelper implements Framework.Constants {

  /**
   * The result set that backs this class and provides the real data
   */
    private ResultSet resultSet = null;

    /**
     * The metadata backing this result set. This is cached for efficiency and is populated only when required.
     */
    private ResultSetMetaData metaData = null;

    /**
     * Create a result set helper based on the passed result set.
     * @throws NullPointerException if pResultSet is null
     */
    public ResultSetHelper(ResultSet pResultSet) {
        super();
        if (pResultSet == null) {
          throw new NullPointerException("pResultSet cannot be null");
        }
        this.resultSet = pResultSet;
    }

    /**
     * Releases this <code>ResultSet</code> object's database and
     * JDBC resources immediately instead of waiting for
     * this to happen when it is automatically closed.
     *
     * <P><B>Note:</B> A <code>ResultSet</code> object
     * is automatically closed by the
     * <code>Statement</code> object that generated it when
     * that <code>Statement</code> object is closed,
     * re-executed, or is used to retrieve the next result from a
     * sequence of multiple results. A <code>ResultSet</code> object
     * is also automatically closed when it is garbage collected. 
     *
     * @exception SQLException if a database access error occurs
     */
    public void close() {
        try {
            this.resultSet.close();
        } catch (SQLException e) {
            throw DBUtilities.translateSQLException(0,e);
        }
    }

    /**
     * Moves the cursor down one row from its current position.
     * A <code>ResultSet</code> cursor is initially positioned
     * before the first row; the first call to the method
     * <code>next</code> makes the first row the current row; the
     * second call makes the second row the current row, and so on.
     *
     * <P>If an input stream is open for the current row, a call
     * to the method <code>next</code> will
     * implicitly close it. A <code>ResultSet</code> object's
     * warning chain is cleared when a new row is read.
     *
     * @return <code>true</code> if the new current row is valid;
     * <code>false</code> if there are no more rows
     */
    public boolean next() {
        try {
            return this.resultSet.next();
        } catch (SQLException e) {
            // TF:10/8/07:Under Sybase in particular, there can be errors on getting
            // the next row if there are no results in the result set (not consistently,
            // but just occasionally)
            // Logger.getLogger(getClass()).error("ResultSetHelper.next(): ",e);
            //   throw DBUtilities.translateSQLException(0,e);
            return false;
        }
    }

    /**
     * Moves the cursor to the given row number in
     * this <code>ResultSet</code> object.
     *
     * <p>If the row number is positive, the cursor moves to
     * the given row number with respect to the
     * beginning of the result set.  The first row is row 1, the second
     * is row 2, and so on.
     *
     * <p>If the given row number is negative, the cursor moves to
     * an absolute row position with respect to
     * the end of the result set.  For example, calling the method
     * <code>absolute(-1)</code> positions the
     * cursor on the last row; calling the method <code>absolute(-2)</code>
     * moves the cursor to the next-to-last row, and so on.
     *
     * <p>An attempt to position the cursor beyond the first/last row in
     * the result set leaves the cursor before the first row or after
     * the last row.
     *
     * <p><B>Note:</B> Calling <code>absolute(1)</code> is the same
     * as calling <code>first()</code>. Calling <code>absolute(-1)</code>
     * is the same as calling <code>last()</code>.
     *
     * @param row the number of the row to which the cursor should move.
     *        A positive number indicates the row number counting from the
     *        beginning of the result set; a negative number indicates the
     *        row number counting from the end of the result set
     * @return <code>true</code> if the cursor is moved to a position in this
     * <code>ResultSet</code> object;
     * <code>false</code> if the cursor is before the first row or after the
     * last row
     * @exception SQLException if a database access error
     * occurs; this method is called on a closed result set
     * or the result set type is <code>TYPE_FORWARD_ONLY</code>
     * @exception UsageException if the JDBC driver does not support
     * this method
     */
    public boolean absolute(int row) {
      try {
        return this.resultSet.absolute(row);
        } catch (SQLException e) {
          throw processException(e);
        }
    }
   
    /**
     * Retrieves the current row number.  The first row is number 1, the
     * second number 2, and so on. 
     * <p>
     * <strong>Note:</strong>Support for the <code>getRow</code> method
     * is optional for <code>ResultSet</code>s with a result
     * set type of <code>TYPE_FORWARD_ONLY</code>
     *
     * @return the current row number; <code>0</code> if there is no current row
     * @exception SQLException if a database access error occurs
     * or this method is called on a closed result set
     * @exception UsageException if the JDBC driver does not support
     * this method
     */
    public int getRow() {
      try {
        return this.resultSet.getRow();
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Retrieves whether the cursor is after the last row in
     * this <code>ResultSet</code> object.
     *
     * @return <code>true</code> if the cursor is after the last row;
     * <code>false</code> if the cursor is at any other position or the
     * result set contains no rows
     * @exception UsageException if a database access error occurs
     */
    public boolean isAfterLast() {
      try {
        return this.resultSet.isAfterLast();
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Moves the cursor to the first row in
     * this <code>ResultSet</code> object.
     *
     * @return <code>true</code> if the cursor is on a valid row;
     * <code>false</code> if there are no rows in the result set
     * @exception SQLException if a database access error
     * occurs; this method is called on a closed result set
     * or the result set type is <code>TYPE_FORWARD_ONLY</code>
     * @exception UsageException if the JDBC driver does not support
     * this method
     */
    public boolean first() {
      try {
        return this.resultSet.first();
        } catch (SQLException e) {
          throw processException(e);
        }
    }
   
    /**
     * Moves the cursor to the last row in
     * this <code>ResultSet</code> object.
     *
     * @return <code>true</code> if the cursor is on a valid row;
     * <code>false</code> if there are no rows in the result set
     * @exception SQLException if a database access error
     * occurs; this method is called on a closed result set
     * or the result set type is <code>TYPE_FORWARD_ONLY</code>
     * @exception UsageException if the JDBC driver does not support
     * this method
     */
    public boolean last() {
      try {
        return this.resultSet.last();
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * @see {@link ResultSetHelper#getDataValue(int, Class)}
     *
     * Created this method so we could pass in an already instantiated DataValue. CraigM:24/09/2008.
     *
     * @param pColumnID
     * @param pDataValue
     */
    public void getDataValue(String pColumnID, DataValue pDataValue) {
        try {
            int aColumn = this.resultSet.findColumn(pColumnID);
            this.getDataValue(aColumn, pDataValue);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * @see {@link ResultSetHelper#getDataValue(String, Class)}
     *
     * Created this method so we could pass in an already instantiated DataValue.
     *
     * @param pColumnID
     * @param pDataValue
     */
    public void getDataValue(TextData pColumnID, DataValue pDataValue) {
        if (pColumnID == null) {
      this.getDataValue((String)null, pDataValue);
    } else {
      this.getDataValue(pColumnID.getValue(), pDataValue);
    }
    }

    /**
     * The getDataValue method returns the value of the column that you specify as an instance of the DataValue class you specify. If
     * the types are mismatched between the database and the specified class instance, type conversion is attempted. If this type
     * conversion fails a UsageException is thrown.
     * <p>
   * The position parameter specifies the column number for the column within the result set. If there is no matching position,
   * this method raises an exception of the UsageException class, with a reason code of SP_ER_PARAMETERERROR.
     * @param pColumnID the column id to map the data value from
     * @return a DataValue instance of the specified typethat contains the value in the column
     * @throws UsageException if there is a type mismatch between the specified type and the database, or if data exceptions occur.
     */
    public DataValue getDataValue(int pColumnID, Class<? extends DataValue> c) {
        try {
            DataValue tn = c.newInstance();
            this.getDataValue(pColumnID, tn); // CraigM:24/09/2008 - Moved code into getDataValue(int, DataValue) method

            return tn;
        } catch (IllegalAccessException e1){
          throw processException("ResultSetHelper: Cannot construct the property type", e1);
        } catch (InstantiationException e2) {
          throw processException("ResultSetHelper: Cannot construct the property type", e2);
        }
    }
   
    /**
     * @see {@link ResultSetHelper#getDataValue(int, Class)}
     *
     * Created this method so we could pass in an already instantiated DataValue. CraigM:24/09/2008.
     *
     * @param pColumnID
     * @param pDataValue
     */
    public void getDataValue(int pColumnID, DataValue pDataValue) {
      // CraigM:25/09/2008 - Null check
      if (pDataValue == null) {
        throw new UsageException("The DataValue object specified for column "+pColumnID+" was null");
      }
      try {
          Class<?> classType = pDataValue.getClass();
        if (this.metaData == null)
          this.metaData = this.resultSet.getMetaData();

        int type = this.metaData.getColumnType(pColumnID);
        boolean isNullable = (this.metaData.isNullable(pColumnID) != ResultSetMetaData.columnNoNulls);
        switch (type) {
        case Types.BIT:
        case Types.BOOLEAN:
          Object o = resultSet.getObject(pColumnID);

          if ((o == null || isNullable) && (BooleanNullable.class.isAssignableFrom(classType) && (resultSet.wasNull()) )) {
            ((BooleanNullable)pDataValue).setNull();
          } else {
            ((BooleanData)pDataValue).setValue(this.mapBooleanFromDB(o));
          }
          break;

        case Types.BIGINT:
        case Types.INTEGER:
        case Types.SMALLINT:
        case Types.TINYINT:
          int intr = resultSet.getInt(pColumnID);
          if (BooleanData.class.isAssignableFrom(classType))
          {
            if ((isNullable) && (BooleanNullable.class.isAssignableFrom(classType) && (resultSet.wasNull()) )) {
              ((BooleanNullable)pDataValue).setIsNull(true);
            } else {
              ((BooleanData)pDataValue).setI4Value(intr);
            }

          }
          else
          {
            // TF:07/11/2009:DET-125:Changed this to handle other NumericData types besides IntegerData
            if (isNullable && NumericData.class.isAssignableFrom(classType) && resultSet.wasNull() && ((NumericData)pDataValue).isNullable()) {
              ((NumericData)pDataValue).setIsNull(true);
            }
            // DavidQ:23/7/2008 - Deal with possible mapping of TinyInt from an RDB to a TextData
            // DavidQ - Begin
            else if (pDataValue instanceof TextData)
            {
              if ((isNullable) && (TextNullable.class.isAssignableFrom(classType) && (resultSet.wasNull()) )) {
                ((TextNullable)pDataValue).setIsNull(true);
              } else {
                ((TextData)pDataValue).setValue(intr);
              }
            }
            // DavidQ - End
            else {
              ((NumericData)pDataValue).setValue(intr);
            }
          }
          break;

        case Types.FLOAT:    // TF:8/10/07: Added this here -- possibly should be near the DOUBLE type instead?
        case Types.NUMERIC:
          Object sqlType = this.resultSet.getObject(pColumnID);
          if (sqlType == null && pDataValue instanceof DecimalNullable) {
            sqlType = new BigDecimal(0);
          }

          // ISSUE 501 - Added check for scale - if scale is 0 then make
          // Integer
          int scale = this.metaData.getScale(pColumnID);

          if (sqlType instanceof BigDecimal &&
              (scale > 0 || pDataValue instanceof DecimalData || pDataValue instanceof DoubleData)) {
            double doub = resultSet.getDouble(pColumnID);

            if (pDataValue instanceof TextData) {
              if ((isNullable) && (TextNullable.class.isAssignableFrom(classType) && (resultSet.wasNull()) )) {
                ((TextNullable)pDataValue).setIsNull(true);
              } else {
                ((TextData)pDataValue).setValue(doub);
              }
            } else if (DecimalNullable.class.isAssignableFrom(classType)){
              if (isNullable  && resultSet.wasNull())
                ((DecimalNullable)pDataValue).setNull();
              else
                ((DecimalNullable)pDataValue).setValue(doub);

            } else if (DoubleData.class.isAssignableFrom(classType) ) {
              // AD:17/12/2008: Fixed to allow DoubleData rather than only DoubleNullable
              if (isNullable  && resultSet.wasNull())
                ((DoubleData)pDataValue).setIsNull(true);
              else
                ((DoubleData)pDataValue).setValue(doub);


            } else {
              ((DecimalData)pDataValue).setValue(doub);
            }

          } else {
            int intr1 = resultSet.getInt(pColumnID);

            if (isNullable && resultSet.wasNull()) {
              // TF:8/10/07: Simplified this logic
              pDataValue.setIsNull(true);
            }

            if (isNullable && !resultSet.wasNull()) {
              if (DecimalNullable.class.isAssignableFrom(classType) ) {
                ((DecimalNullable)pDataValue).setValue(intr1);
              } else if (TextData.class.isAssignableFrom(classType)) {
                ((TextData)pDataValue).setIntegerValue(intr1);
              } else if (DoubleData.class.isAssignableFrom(classType)) {
                ((DoubleData)pDataValue).setValue(intr1);
              } else if (BooleanData.class.isAssignableFrom(classType)) {
                ((BooleanData)pDataValue).setValue(intr1 == 0 ? false : true);
              } else {
                // TF:8/10/07: Simplified this logic
                ((IntegerData)pDataValue).setValue(intr1);
              }
            }

            if (!isNullable) {
              if (DecimalData.class.isAssignableFrom(classType)) {
                ((DecimalData)pDataValue).setValue(intr1);
              } else if (TextData.class.isAssignableFrom(classType)) {
                ((TextData)pDataValue).setIntegerValue(intr1);
              } else if (DoubleData.class.isAssignableFrom(classType)) {
                ((DoubleData)pDataValue).setValue(intr1);
              } else if (BooleanData.class.isAssignableFrom(classType)) {
                ((BooleanData)pDataValue).setValue(intr1 == 0 ? false : true);
              } else {
                ((IntegerData)pDataValue).setValue(intr1);
              }
            }


            //                if ((isNullable) && (DecimalNullable.class.isAssignableFrom(c) && (resultSet.wasNull()) )) {
            //                    ((DecimalNullable)tn).setIsNull(true);
            //                } else {
            //                  ((DecimalData)tn).setValue(intr1);
            //                }
            //               
            //                if ((isNullable) && (IntegerNullable.class.isAssignableFrom(c) && (resultSet.wasNull()) )) {
            //                    ((IntegerNullable)tn).setIsNull(true);
            //                } else {
            //                  ((IntegerData)tn).setValue(intr1);
            //                }
          }
          break;

        case Types.DECIMAL:
          double doub = resultSet.getDouble(pColumnID);
          if (isNullable && resultSet.wasNull()) {
            pDataValue.setIsNull(true);
          } else {
            // TF:29/07/2008:Cleaned up this code
            if (NumericData.class.isAssignableFrom(classType)) {
              ((NumericData)pDataValue).setValue(doub);
            } else if (BooleanData.class.isAssignableFrom(classType)) {
              ((BooleanData)pDataValue).setValue(doub == 0 ? false : true);
            } else {
              ((TextData)pDataValue).setValue(doub);
            }
          }
          break;

        case Types.REAL:
        case Types.DOUBLE:
          double doub1 = resultSet.getDouble(pColumnID);
          if (isNullable && resultSet.wasNull()) {
            pDataValue.setIsNull(true);
          } else {
            // TF:29/07/2008:Cleaned up this code
            if (NumericData.class.isAssignableFrom(classType)) {
              ((NumericData)pDataValue).setValue(doub1);
            } else if (BooleanData.class.isAssignableFrom(classType)) {
              ((BooleanData)pDataValue).setValue(doub1 == 0 ? false : true);
            } else {
              ((TextData)pDataValue).setValue(doub1);
            }
          }
          break;

          // case Types.BINARY:
          // return this.getBinaryData(pColumnID);

        case Types.CHAR:
        case Types.CLOB:
        case Types.LONGVARCHAR:
        case Types.VARCHAR:
          // TF:29/07/2008:non-CHAR column types seem to keep whitespaces on their values
          // (may be database specific, tested on Oracle)
          String str = resultSet.getString(pColumnID);
          if ((isNullable) && (TextNullable.class.isAssignableFrom(classType) ) && (resultSet.wasNull())) {
            ((TextNullable)pDataValue).setIsNull(true);
          } else {
            // TF:29/07/2008:CHAR column types seem to trim their values, no other column types do
            // (may be database specific, tested on Oracle)
            if (pDataValue instanceof TextData) {
              pDataValue.setValue(determineStringToReturn(str, pColumnID, type));
            }
            else if (str == null){
              pDataValue.setValue((TextData)null);
            }
            else {
              TextData aTD = new TextData(determineStringToReturn(str, pColumnID, type));
              pDataValue.setValue(aTD);
            }
          }
          break;

        case Types.DATE:
        case Types.TIME:
        case Types.TIMESTAMP:
          java.sql.Timestamp date = resultSet.getTimestamp(pColumnID);
          if ((isNullable) && (DateTimeNullable.class.isAssignableFrom(classType) && (resultSet.wasNull()) )) {
            ((DateTimeNullable)pDataValue).setNull();
          }else if (TextNullable.class.isAssignableFrom(classType)){
            ((TextNullable)pDataValue).setValue(date.toString());
          }else if (TextData.class.isAssignableFrom(classType)){
            //KDB:3 Nov 2008: check that date isn't null first - if so set the textdata to an empty string
            if (date==null) {
              ((TextData)pDataValue).setValue("");
            } else {
              ((TextData)pDataValue).setValue(date.toString());
            }
          } else {
            ((DateTimeData)pDataValue).setValue(date);
          }
          break;
         
            // TF:23/02/2009:JIRA DET-75:handle binary data within the database
            case Types.BLOB:
            case Types.BINARY:
            case Types.LONGVARBINARY:
            case Types.VARBINARY:
              BinaryNullable value = this.getBinaryNullable(pColumnID);
              if (value.isNull() && pDataValue.isNullable()) {
                pDataValue.setIsNull(true);
              }
              else if (TextData.class.isAssignableFrom(classType)){
          if (value.isNull()) {
            ((TextData)pDataValue).setValue("");
          } else {
            ((TextData)pDataValue).setValue(value.toString());
          }
        } else {
          ((BinaryData)pDataValue).setValue(value);
        }
              break;
        }
      } catch (SQLException e) {
        throw processException(e);
      }
    }

    /**
     * The getDataValue method returns the value of the column that you specify by position as an appropriate sub-class of DataValue.
     * The actual class returned depends upon the type of the column in the database, and in some cases the scale and precision of
     * this column.<p>
     * <p>
     * For example, if the column contains an integer, the object will be an IntegerNullable object. Therefore, if you wish to
     * perform operations on this object, you may need to cast it. The following table shows the types returned: <p>
     * <p>
     * <table border=2 >
     *   <tr><th>Column Type</th><th>Returned Type</th></tr>
     *   <tr><td>BIT<br>BOOLEAN</td><td>BooleanNullable</td></tr>
     *   <tr><td>BIGINT<br>INTEGER<br>SMALLINT<br>TINYINT</td><td>IntegerNullable</td></tr>
     *   <tr><td>NUMERIC</td><td>DecimalNullable<br>DoubleNullable</td></tr>
     *   <tr><td>DECIMAL</td><td>DecimalNullable<br>IntegerNullable</td></tr>
     *   <tr><td>REAL<br>DOUBLE</td><td>DoubleNullable</td></tr>
     *   <tr><td>CHAR<br>CLOB<br>LONGVARCHAR<br>VARCHAR</td><td>TextNullable</td></tr>
     *   <tr><td>DATE<br>TIME<br>TIMESTAMPE<br></td><td>DateTimeNullable</td></tr>
     * </table>
     * <p>
   * The position parameter specifies the column number for the column within the result set. If there is no matching position,
   * this method raises an exception of the UsageException class, with a reason code of SP_ER_PARAMETERERROR.
     * @param pColumnID the column id to map the data value from
     * @return a DataValue instance that contains the value in the column
     */
    public DataValue getDataValue(int pColumnID) {
        try {
            if (this.metaData == null)
                this.metaData = this.resultSet.getMetaData();
            int type = this.metaData.getColumnType(pColumnID);
            // TF:8/8/07:It seems that we always get one of the nullable columns back from this method, irrespective
            // of whether the underlying column is nullable or not, so fixed this up
            switch (type) {
            case Types.BIT:
            case Types.BOOLEAN:
                return this.getBooleanNullable(pColumnID);

            case Types.BIGINT:
            case Types.INTEGER:
            case Types.SMALLINT:
            case Types.TINYINT:
                return this.getIntegerNullable(pColumnID);

            case Types.NUMERIC: {

                // ISSUE 501 - Added check for scale - if scale is 0 then make
                // Integer
                int scale = this.metaData.getScale(pColumnID);

                // TF:10/8/07:Checked to see if the type was null before determining
                // the scale, and returned a Double nullable in this case.
                Object sqlType = this.resultSet.getObject(pColumnID);
                if (sqlType instanceof BigDecimal && scale > 0) {
                    return this.getDecimalNullable(pColumnID, scale);
                }
                else if (sqlType == null && scale > 0) {
                    return this.getDoubleNullable(pColumnID);
                } else {
                  // TF:29/07/2008:If we return a numeric column, everyone casts it to a double nullable,
                  // so it appears this needs to be returned in this case
                    // return this.getIntegerNullable(pColumnID);
                  return this.getDoubleNullable(pColumnID);
                }
            }
            case Types.DECIMAL: {

                int scale2 = this.metaData.getScale(pColumnID);

                Object sqlType = this.resultSet.getObject(pColumnID);
                if ((sqlType instanceof BigDecimal || sqlType == null) && scale2 > 0) {
                    return this.getDecimalNullable(pColumnID);
                } else {
                    return this.getIntegerNullable(pColumnID);
                }
            }
            case Types.REAL:
            case Types.DOUBLE:
                return this.getDoubleNullable(pColumnID);

            // case Types.BINARY:
            // return this.getBinaryData(pColumnID);

            case Types.CHAR:
            case Types.CLOB:
            case Types.LONGVARCHAR:
            case Types.VARCHAR:
                return this.getTextNullable(pColumnID, type);

            case Types.DATE:
            case Types.TIME:
            case Types.TIMESTAMP:
                return this.getDateTimeNullable(pColumnID);

            // TF:23/02/2009:JIRA DET-75:handle binary data within the database
            case Types.BLOB:
            case Types.BINARY:
            case Types.LONGVARBINARY:
            case Types.VARBINARY:
              return this.getBinaryNullable(pColumnID);
             
            default:
                return null;
            }
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * The getDataValue method returns the value of the column that you specify by position as an appropriate sub-class of DataValue.
     * The actual class returned depends upon the type of the column in the database, and in some cases the scale and precision of
     * this column.<p>
     * <p>
     * For example, if the column contains an integer, the object will be an IntegerNullable object. Therefore, if you wish to
     * perform operations on this object, you may need to cast it. The following table shows the types returned: <p>
     * <p>
     * <table border=2 >
     *   <tr><th>Column Type</th><th>Returned Type</th></tr>
     *   <tr><td>BIT<br>BOOLEAN</td><td>BooleanNullable</td></tr>
     *   <tr><td>BIGINT<br>INTEGER<br>SMALLINT<br>TINYINT</td><td>IntegerNullable</td></tr>
     *   <tr><td>NUMERIC</td><td>DecimalNullable<br>DoubleNullable</td></tr>
     *   <tr><td>DECIMAL</td><td>DecimalNullable<br>IntegerNullable</td></tr>
     *   <tr><td>REAL<br>DOUBLE</td><td>DoubleNullable</td></tr>
     *   <tr><td>CHAR<br>CLOB<br>LONGVARCHAR<br>VARCHAR</td><td>TextNullable</td></tr>
     *   <tr><td>DATE<br>TIME<br>TIMESTAMPE<br></td><td>DateTimeNullable</td></tr>
     * </table>
     * <p>
   * The position parameter specifies the column name for the column within the result set. If there is no matching column,
   * this method raises an exception of the UsageException class, with a reason code of SP_ER_PARAMETERERROR.
     * @param pColumnID the column id to map the data value from
     * @return a DataValue instance that contains the value in the column
     */
    public DataValue getDataValue(String pColumnID) {
        try {
            int aColumn = this.resultSet.findColumn(pColumnID);
            return this.getDataValue(aColumn);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * The getDataValue method returns the value of the column that you specify as an instance of the DataValue class you specify. If
     * the types are mismatched between the database and the specified class instance, type conversion is attempted. If this type
     * conversion fails a UsageException is thrown.
     * <p>
   * The position parameter specifies the column name for the column within the result set. If there is no matching position,
   * this method raises an exception of the UsageException class, with a reason code of SP_ER_PARAMETERERROR.
     * @param pColumnID the column id to map the data value from
     * @return a DataValue instance of the specified typethat contains the value in the column
     * @throws UsageException if there is a type mismatch between the specified type and the database, or if data exceptions occur.
     */
    public DataValue getDataValue(String pColumnID, Class<? extends DataValue> clazz) {
        try {
            int aColumn = this.resultSet.findColumn(pColumnID);
            return this.getDataValue(aColumn, clazz);
        } catch (SQLException e) {
          throw processException(e);
        }

    }
   
    private TextNullable getTextNullable(int pColumnID, int pColumnType) {
        try {
            TextNullable tn = new TextNullable();

            String str = resultSet.getString(pColumnID);
            if (resultSet.wasNull()) {
                tn.setIsNull(true);
            }
            else {
              // Whether we truncate or not depends on the database
              tn.setValue(determineStringToReturn(str, pColumnID, pColumnType));
            }

            return tn;
        } catch (SQLException e) {
          throw processException(e);
        }
    }
   
    /**
     * Read a column from the database, returning the result as a TextNullable. If the column in the database that was
     * read was <code>null</code>, then the resulting TextNullable class will have it's Null property set to true.
     * @param pColumnID the ordinal number of the column to read
     * @return a TextNullable instance containing the value of the column in the database
     */
    public TextNullable getTextNullable(int pColumnID) {
        try {
            TextNullable tn = new TextNullable();

            String str = resultSet.getString(pColumnID);
            if (resultSet.wasNull()) {
                tn.setIsNull(true);
            }
            else {
              // Whether we truncate or not depends on the database
              tn.setValue(determineStringToReturn(str, pColumnID));
            }

            return tn;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Read a column from the database, returning the result as a TextNullable. If the column in the database that was
     * read was <code>null</code>, then the resulting TextNullable class will have it's Null property set to true.
     * @param columnName the name number of the column to read
     * @return a TextNullable instance containing the value of the column in the database
     * @throws UsageException with reason code of SP_ER_PARAMETERERROR if no column with the passed name exists in the database
     */
    public TextNullable getTextNullable(String columnName) {
        try {
          return getTextNullable(this.resultSet.findColumn(columnName));
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Read a column from the database, returning the result as a TextData. If the column in the database that was
     * read was <code>null</code>, then the resulting TextNullable class will have it's Null property set to true.
     * @param pColumnID the ordinal number of the column to read
     * @return a TextData instance containing the value of the column in the database
     */
    public TextData getTextData(int pColumnID) {
        try {
            // AD:22/07/2008 - Check if value is null and raise usage exception if it is
            Object o = resultSet.getObject(pColumnID);
            if (o == null || resultSet.wasNull()) {
                throw new UsageException(
                        "getTextData(int) could not handle column " + pColumnID + ". Result =" + o,
                        SP_ER_PARAMETERERROR, SP_ER_USER, UsageException.qq_Resolver.cMESSAGE_REASONCODE_SEVERITY);
            }
            return new TextData(determineStringToReturn(resultSet.getString(pColumnID), pColumnID));
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Read a column from the database, returning the result as a TextData.
     * @param columnName the name number of the column to read
     * @return a TextData instance containing the value of the column in the database
     * @throws UsageException with reason code of SP_ER_PARAMETERERROR if no column with the passed name exists in the database
     */
    public TextData getTextData(String columnName) {
        try {
          return getTextData(this.resultSet.findColumn(columnName));
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Read a column from the database, returning the result as an IntegerNullable. If the column in the database that was
     * read was <code>null</code>, then the resulting IntegerNullable class will have it's Null property set to true.
     * @param pColumnID the ordinal number of the column to read
     * @return a IntegerNullable instance containing the value of the column in the database
     */
    public IntegerNullable getIntegerNullable(int pColumnID) {
        IntegerNullable in = new IntegerNullable();

        try {
            int intr = resultSet.getInt(pColumnID);
            if (resultSet.wasNull()) {
                in.setIsNull(true);
            } else {
                in.setValue(intr);
            }

            return in;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Read a column from the database, returning the result as an IntegerNullable. If the column in the database that was
     * read was <code>null</code>, then the resulting IntegerNullable class will have it's Null property set to true.
     * @param columnName the name number of the column to read
     * @return a IntegerNullable instance containing the value of the column in the database
     * @throws UsageException with reason code of SP_ER_PARAMETERERROR if no column with the passed name exists in the database
     */
    public IntegerNullable getIntegerNullable(String pColumnName) {
        try {
            IntegerNullable in = new IntegerNullable();

            int intr = resultSet.getInt(pColumnName);
            if (resultSet.wasNull()) {
                in.setIsNull(true);
            } else {
                in.setValue(intr);
            }

            return in;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Read a column from the database, returning the result as an IntegerNullable. If the column in the database that was
     * read was <code>null</code>, then the resulting IntegerNullable class will have it's Null property set to true.
     * @param pColumnID the ordinal number of the column to read
     * @return a TextData instance containing the value of the column in the database
     */
    public IntegerData getIntegerData(int pColumnID) {
        try {
            // AD:22/07/2008 - Check if value is null and raise usage exception if it is
            Object o = resultSet.getObject(pColumnID);
            if (o == null || resultSet.wasNull()) {
                throw new UsageException(
                        "getTextData(String) could not handle column " + pColumnID + ". Result =" + o,
                        SP_ER_PARAMETERERROR, SP_ER_USER, UsageException.qq_Resolver.cMESSAGE_REASONCODE_SEVERITY);
            }
            IntegerData id = new IntegerData(resultSet.getInt(pColumnID));
            return id;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Read a column from the database, returning the result as an IntegerData.
     * @param columnName the name number of the column to read
     * @return a IntegerData instance containing the value of the column in the database
     * @throws UsageException with reason code of SP_ER_PARAMETERERROR if no column with the passed name exists in the database
     */
    public IntegerData getIntegerData(String pColumnName) {
        try {
            // AD:22/07/2008 - Check if value is null and raise usage exception if it is
            Object o = resultSet.getObject(pColumnName);
            if (o == null || resultSet.wasNull()) {
                throw new UsageException(
                        "getIntegerData(String) could not handle column " + pColumnName + ". Result =" + o,
                        SP_ER_PARAMETERERROR, SP_ER_USER, UsageException.qq_Resolver.cMESSAGE_REASONCODE_SEVERITY);
            }
            IntegerData id = new IntegerData(resultSet.getInt(pColumnName));
            return id;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Read a column from the database, returning the result as a BooleanNullable. If the column in the database that was
     * read was <code>null</code>, then the resulting BooleanNullable class will have it's Null property set to true.
     * @param pColumnID the ordinal number of the column to read
     * @return a BooleanNullable instance containing the value of the column in the database
     */
    public BooleanNullable getBooleanNullable(int pColumnID) {
        Object o = null;
        try {
            o = resultSet.getObject(pColumnID);

            if (o == null || resultSet.wasNull()) {
                BooleanNullable result = new BooleanNullable();
                result.setNull();
                return result;
            } else {
                return new BooleanNullable(this.mapBooleanFromDB(o));
            }
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Read a column from the database, returning the result as a BooleanNullable. If the column in the database that was
     * read was <code>null</code>, then the resulting TextNullable class will have it's Null property set to true.
     * @param columnName the name number of the column to read
     * @return a BooleanNullable instance containing the value of the column in the database
     * @throws UsageException with reason code of SP_ER_PARAMETERERROR if no column with the passed name exists in the database
     */
    public BooleanNullable getBooleanNullable(String pColumnName) {
        Object o = null;
        try {
            o = resultSet.getObject(pColumnName);

            if (o == null || resultSet.wasNull()) {
                BooleanNullable result = new BooleanNullable();
                result.setNull();
                return result;
            } else {
                return new BooleanNullable(this.mapBooleanFromDB(o));
            }
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Read a column from the database, returning the result as a BooleanData. If the column in the database that was
     * read was <code>null</code>, then the resulting TextNullable class will have it's Null property set to true.
     * @param pColumnID the ordinal number of the column to read
     * @return a BooleanData instance containing the value of the column in the database
     */
    public BooleanData getBooleanData(int pColumnID) {
        try {
            Object o = resultSet.getObject(pColumnID);
            if (o == null || resultSet.wasNull()) {
                throw new UsageException(
                        "getBooleanData(int) could not handle column "
                                + pColumnID + ". Result =" + o);

            } else {
                return new BooleanData(this.mapBooleanFromDB(o));
            }
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Read a column from the database, returning the result as a BooleanData.
     * @param columnName the name number of the column to read
     * @return a BooleanData instance containing the value of the column in the database
     * @throws UsageException with reason code of SP_ER_PARAMETERERROR if no column with the passed name exists in the database
     */
    public BooleanData getBooleanData(String pColumnName) {
        try {
            Object o = resultSet.getObject(pColumnName);
            if (o == null || resultSet.wasNull()) {
                throw new UsageException(
                        "getBooleanData(int) could not handle column "
                                + pColumnName + ". Result =" + o);

            } else {
                return new BooleanData(this.mapBooleanFromDB(o));
            }
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Read a column from the database, returning the result as a DecimalNullable. If the column in the database that was
     * read was <code>null</code>, then the resulting DecimalNullable class will have it's Null property set to true.
     * @param pColumnID the ordinal number of the column to read
     * @return a DecimalNullable instance containing the value of the column in the database
     */
    public DecimalNullable getDecimalNullable(int pColumnID) {
        try {
            DecimalNullable dn = new DecimalNullable();

            double doub = resultSet.getDouble(pColumnID);
            if (resultSet.wasNull()) {
                dn.setNull();
            } else {
                dn.setValue(doub);
            }

            return dn;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public DecimalNullable getDecimalNullable(int pColumnID, int pScale) {
        try {
            DecimalNullable dn = new DecimalNullable();
            dn.setScale(pScale);

            double doub = resultSet.getDouble(pColumnID);
            if (resultSet.wasNull()) {
                dn.setNull();
            } else {
                dn.setValue(doub);
            }

            return dn;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public DecimalNullable getDecimalNullable(String pColumnName) {
        try {
            DecimalNullable dn = new DecimalNullable();

            double doub = resultSet.getDouble(pColumnName);
            if (resultSet.wasNull()) {
                dn.setNull();
            } else {
                dn.setValue(doub);
            }

            return dn;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public DecimalNullable getDecimalNullable(String pColumnName, int pScale) {
        try {
            DecimalNullable dn = new DecimalNullable();
            dn.setScale(pScale);

            double doub = resultSet.getDouble(pColumnName);
            if (resultSet.wasNull()) {
                dn.setNull();
            } else {
                dn.setValue(doub);
            }

            return dn;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public DecimalData getDecimalData(int pColumnID) {
        try {
            // AD:22/07/2008 - Check if value is null and raise usage exception if it is
            Object o = resultSet.getObject(pColumnID);
            if (o == null || resultSet.wasNull()) {
                throw new UsageException(
                        "getDecimalData(int) could not handle column " + pColumnID + ". Result =" + o,
                        SP_ER_PARAMETERERROR, SP_ER_USER, UsageException.qq_Resolver.cMESSAGE_REASONCODE_SEVERITY);
            }
            DecimalData dd = new DecimalData(resultSet.getDouble(pColumnID));
            return dd;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public DecimalData getDecimalData(String pColumnName) {
        try {
            // AD:22/07/2008 - Check if value is null and raise usage exception if it is
            Object o = resultSet.getObject(pColumnName);
            if (o == null || resultSet.wasNull()) {
                throw new UsageException(
                        "getDecimalData(String) could not handle column " + pColumnName + ". Result =" + o,
                        SP_ER_PARAMETERERROR, SP_ER_USER, UsageException.qq_Resolver.cMESSAGE_REASONCODE_SEVERITY);
            }
            DecimalData dd = new DecimalData(resultSet.getDouble(pColumnName));
            return dd;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public DoubleNullable getDoubleNullable(int pColumnID) {
        try {
            DoubleNullable dn = new DoubleNullable();

            double doub = resultSet.getDouble(pColumnID);
            if (resultSet.wasNull()) {
                dn.setNull();
            } else {
                dn.setValue(doub);
            }
            return dn;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public DoubleNullable getDoubleNullable(String pColumnName) {
        try {
            DoubleNullable dn = new DoubleNullable();

            double doub = resultSet.getDouble(pColumnName);
            if (resultSet.wasNull()) {
                dn.setNull();
            } else {
                dn.setValue(doub);
            }
            return dn;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public DoubleData getDoubleData(int pColumnID) {
        try {
            // AD:22/07/2008 - Check if value is null and raise usage exception if it is
            Object o = resultSet.getObject(pColumnID);
            if (o == null || resultSet.wasNull()) {
                throw new UsageException(
                        "getDoubleData(int) could not handle column " + pColumnID + ". Result =" + o,
                        SP_ER_PARAMETERERROR, SP_ER_USER, UsageException.qq_Resolver.cMESSAGE_REASONCODE_SEVERITY);
            }
            DoubleData dd = new DoubleData(resultSet.getDouble(pColumnID));
            return dd;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public DoubleData getDoubleData(String pColumnName) {
        try {
            // AD:22/07/2008 - Check if value is null and raise usage exception if it is
            Object o = resultSet.getObject(pColumnName);
            if (o == null || resultSet.wasNull()) {
                throw new UsageException(
                        "getDoubleData(String) could not handle column " + pColumnName + ". Result =" + o,
                        SP_ER_PARAMETERERROR, SP_ER_USER, UsageException.qq_Resolver.cMESSAGE_REASONCODE_SEVERITY);
            }
            DoubleData dd = new DoubleData(resultSet.getDouble(pColumnName));
            return dd;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public DateTimeNullable getDateTimeNullable(int pColumnID) {
        try {
            DateTimeNullable dn = null;

            java.sql.Timestamp date = resultSet.getTimestamp(pColumnID);
            if (resultSet.wasNull()) {
                dn = new DateTimeNullable();
                dn.setNull();
            } else {
                dn = new DateTimeNullable(date);
            }

            return dn;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public DateTimeNullable getDateTimeNullable(String pColumnName) {
        try {
            DateTimeNullable dn = null;

            java.sql.Timestamp date = resultSet.getTimestamp(pColumnName);
            if (resultSet.wasNull()) {
                dn = new DateTimeNullable();
                dn.setNull();
            } else {
                dn = new DateTimeNullable(date);
            }

            return dn;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public DateTimeData getDateTimeData(int pColumnID) {
        try {
            // AD:22/07/2008 - Check if value is null and raise usage exception if it is
            Object o = resultSet.getObject(pColumnID);
            if (o == null || resultSet.wasNull()) {
                throw new UsageException(
                        "getDateTimeData(int) could not handle column " + pColumnID + ". Result =" + o,
                        SP_ER_PARAMETERERROR, SP_ER_USER, UsageException.qq_Resolver.cMESSAGE_REASONCODE_SEVERITY);
            }
            DateTimeData dt = new DateTimeData(resultSet.getTimestamp(pColumnID));
            return dt;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public DateTimeData getDateTimeData(String pColumnName) {
        try {
            // AD:22/07/2008 - Check if value is null and raise usage exception if it is
            Object o = resultSet.getObject(pColumnName);
            if (o == null || resultSet.wasNull()) {
                throw new UsageException(
                        "getDateTimeData(String) could not handle column " + pColumnName + ". Result =" + o,
                        SP_ER_USER, SP_ER_PARAMETERERROR, UsageException.qq_Resolver.cMESSAGE_REASONCODE_SEVERITY);
            }
            DateTimeData dt = new DateTimeData(resultSet
                    .getTimestamp(pColumnName));
            return dt;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public IntervalNullable getIntervalNullable(int pColumnID) {
        try {
            IntervalNullable result = null;

            String value = resultSet.getString(pColumnID);
            if (resultSet.wasNull()) {
                result = new IntervalNullable();
                result.setIsNull(true);
            } else {
                result = new IntervalNullable(value);
            }

            return result;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public IntervalNullable getIntervalNullable(String pColumnName) {
        try {
            IntervalNullable result = null;

            String value = resultSet.getString(pColumnName);
            if (resultSet.wasNull()) {
                result = new IntervalNullable();
                result.setIsNull(true);
            } else {
                result = new IntervalNullable(value);
            }

            return result;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public IntervalData getIntervalData(int pColumnID) {
        try {
            // AD:22/07/2008 - Check if value is null and raise usage exception if it is
            Object o = resultSet.getObject(pColumnID);
            if (o == null || resultSet.wasNull()) {
                throw new UsageException(
                        "getIntervalData(int) could not handle column " + pColumnID + ". Result =" + o,
                        SP_ER_PARAMETERERROR, SP_ER_USER, UsageException.qq_Resolver.cMESSAGE_REASONCODE_SEVERITY);
            }
            IntervalData id = new IntervalData(resultSet.getString(pColumnID));
            return id;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public IntervalData getIntervalData(String pColumnName) {
        try {
            // AD:22/07/2008 - Check if value is null and raise usage exception if it is
            Object o = resultSet.getObject(pColumnName);
            if (o == null || resultSet.wasNull()) {
                throw new UsageException(
                        "getIntervalData(String) could not handle column " + pColumnName + ". Result =" + o,
                        SP_ER_PARAMETERERROR, SP_ER_USER, UsageException.qq_Resolver.cMESSAGE_REASONCODE_SEVERITY);
            }
            IntervalData id = new IntervalData(resultSet.getString(pColumnName));
            return id;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public ImageNullable getImageNullable(int pColumnID) {
        ImageNullable in = new ImageNullable();
        try {
            byte[] imageArray = resultSet.getBytes(pColumnID);
            if (imageArray == null)
                return in;

            if (resultSet.wasNull()) {
                in.setNull(true);
            } else {
                in.setValue(imageArray);
                in.setNull(false);
            }

            return in;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public ImageNullable getImageNullable(String pColumnName) {
        ImageNullable in = new ImageNullable();
        try {
            byte[] imageArray = resultSet.getBytes(pColumnName);
            if (imageArray == null)
                return in;

            if (resultSet.wasNull()) {
                in.setNull(true);
            } else {
                in.setValue(imageArray);
                in.setNull(false);
            }

            return in;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public ImageData getImageData(int pColumnID) {
        try {
            ImageData id = new ImageData(resultSet.getBytes(pColumnID));
            return id;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public ImageData getImageData(String pColumnName) {
        try {
            ImageData id = new ImageData(resultSet.getBytes(pColumnName));
            return id;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Determine the string to return for a given column in the result set. This method takes care of
     * null trimming or not the string, based on the type of the column in the database in order to
     * simulate exactly what Forte did. The package level visibility is deliberate
     * @param value the value of the string retruned from the database
     * @param pColumnID the number of the column in this result set.
     * @return
     * @throws SQLException
     */
    String determineStringToReturn(String value, int pColumnID) throws SQLException {
      // TF:29/07/2008:Forte would remove trailing spaces from CHAR column types, but no other
      // (such as varchar, clob, etc). We need to mimic this as people rely on it�s ability to
      // automatically truncate or not, depending on their application. Note that this may be
      // database specific, but this is unclear at the moment.
      if (value == null || value.length() == 0) {
        return value;
      }
      if (value.charAt(value.length() - 1) != ' ') {
        // Not ending in a space, just return the value
        return value;
      }
      else {
        // We need to determine if we need to truncate it or not
        if (this.metaData == null) {
          this.metaData = this.resultSet.getMetaData();
        }
        if (this.metaData != null && this.metaData.getColumnType(pColumnID) == Types.CHAR) {
                return StringUtils.removeTrailingSpaces(value);
        }
        else {
          return value;
        }
      }
    }

    private String determineStringToReturn(String value, int pColumnID, int pColumnType) throws SQLException {
      // TF:29/07/2008:Forte would remove trailing spaces from CHAR column types, but no other
      // (such as varchar, clob, etc). We need to mimic this as people rely on it�s ability to
      // automatically truncate or not, depending on their application. Note that this may be
      // database specific, but this is unclear at the moment.
      if (value == null || value.length() == 0) {
        return value;
      }
      if (value.charAt(value.length() - 1) != ' ') {
        // Not ending in a space, just return the value
        return value;
      }
      else {
        // We need to determine if we need to truncate it or not
        if (pColumnType == Types.CHAR) {
                return StringUtils.removeTrailingSpaces(value);
        }
        else {
          return value;
        }
      }
    }

    public String getString(int pColumnID) {
        try {
          return determineStringToReturn(resultSet.getString(pColumnID), pColumnID);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public String getString(String pColumnName) {
        try {
            return getString(this.resultSet.findColumn(pColumnName));
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public int getInt(int ColumnID) {
        try {
            return resultSet.getInt(ColumnID);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public int getInt(String ColumnName) {
        try {
            return resultSet.getInt(ColumnName);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public short getShort(int ColumnID) {
        try {
            return resultSet.getShort(ColumnID);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public short getShort(String ColumnName) {
        try {
            return resultSet.getShort(ColumnName);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public double getDouble(int ColumnID) {
        try {
            return resultSet.getDouble(ColumnID);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public double getDouble(String ColumnName) {
        try {
            return resultSet.getDouble(ColumnName);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public float getFloat(int ColumnID) {
        try {
            return resultSet.getFloat(ColumnID);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public float getFloat(String ColumnName) {
        try {
            return resultSet.getFloat(ColumnName);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public boolean getBoolean(int ColumnID) {
        Object o = null;
        try {
            o = resultSet.getObject(ColumnID);

            if (o == null || resultSet.wasNull()) {
                throw new UsageException(
                        "getBoolean(int) could not handle column "
                                + ColumnID + ". Result =" + o);
            } else {
                return this.mapBooleanFromDB(o);
            }
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public boolean getBoolean(String ColumnName) {
        Object o = null;
        try {
            o = resultSet.getObject(ColumnName);

            if (o == null || resultSet.wasNull()) {
                throw new UsageException(
                        "getBoolean(String) could not handle column "
                                + ColumnName + ". Result =" + o);
            } else {
                return this.mapBooleanFromDB(o);
            }
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public byte getChar(int ColumnID) {
        try {
            return resultSet.getByte(ColumnID);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public byte getChar(String ColumnName) {
        try {
            return resultSet.getByte(ColumnName);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public Date getDate(int ColumnID) {
        try {
            return resultSet.getDate(ColumnID);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public Date getDate(String ColumnName) {
        try {
            return resultSet.getDate(ColumnName);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public java.sql.Time getTime(String ColumnName) {
        try {
            java.sql.Time lvReturn = null;
            lvReturn = resultSet.getTime(ColumnName);
            return lvReturn;
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public java.sql.Timestamp getTimestamp(String ColumnName) {
        try {
            java.sql.Timestamp lvReturn = null;
            lvReturn = resultSet.getTimestamp(ColumnName);
            return lvReturn;
        } catch (SQLException e) {
          throw processException(e);
        }
    }


    private static String cTRUE = "true";
    private static String cFALSE = "false";
    private static String cYES = "Y";
    private static String cNO = "N";
    private static int cFALSE_INT = 0;

    /**
     * Translate the passed object into a boolean. Several databases (RDB, DB2, etc) do not have
     * a native boolean type and hence rely on some kind of translation from a supported type
     * like integer or string to the correct type
     * @param o
     */
    private boolean mapBooleanFromDB(Object o) {
        if (o == null) {
            UsageException errorVar = new UsageException("could not map null to a valid boolean");
            ErrorMgr.addError(errorVar);
            throw errorVar;
        }
        else if (o instanceof Boolean) {
            return ((Boolean)o).booleanValue();
        }
        else if (o instanceof String) {
            String s = (String)o;
            if (cTRUE.equalsIgnoreCase(s)) {
                return true;
            }
            else if (cFALSE.equalsIgnoreCase(s)) {
                return false;
            }
            else if (cYES.equalsIgnoreCase(s)) {
                return true;
            }
            else if (cNO.equalsIgnoreCase(s)) {
                return false;
            }
            else {
                return Boolean.valueOf(s).booleanValue();
            }
        }
        else if (o instanceof Short) {
            return ((Short)o).intValue() != cFALSE_INT;
        }
        else if (o instanceof Integer) {
            return ((Integer)o).intValue() != cFALSE_INT;
        }
        else if (o instanceof BigDecimal) {
            return ((BigDecimal)o).intValue() != cFALSE_INT;
        }
        else {
            UsageException errorVar = new UsageException("Could not map object of type " + o.getClass() + " to boolean");
            ErrorMgr.addError(errorVar);
            throw errorVar;
        }
    }

    /**
     * get a BinaryNullable from specified column of the resultSet (ColumnID)
     * and then convert it to byte[] which is an acceptable constructor argument
     * to the BinaryNullable class
     * 
     * @param ColumnID - the index of the column to be retrieved from the resultSet
     */
    public BinaryNullable getBinaryNullable (int ColumnID) {
        try {

          // TF:23/02/2009:The method of getting the data depends on the underlying
          // type of the result set. For example, if it's stored in the database as
          // BLOB, we must use getBlob, otherwise we must use getBytes
        if (this.metaData == null) {
          this.metaData = this.resultSet.getMetaData();
        }
        if (this.metaData.getColumnType(ColumnID) == Types.BLOB) {
          Blob theBlob = resultSet.getBlob(ColumnID);
              if (theBlob == null || resultSet.wasNull()) {
                return new BinaryNullable(true, BinaryNullable.qq_Resolver.cISNULL);
              }
              else {
                byte[] byteArray = theBlob.getBytes(1, (int)theBlob.length());
                return new BinaryNullable(byteArray);
              }
        }
        else {
              byte[] byteArray = resultSet.getBytes(ColumnID);
 
              if (byteArray == null || resultSet.wasNull()) {
                return new BinaryNullable(true, BinaryNullable.qq_Resolver.cISNULL);
              }
              else {
                  return new BinaryNullable(byteArray);
              }
        }
        }
        catch (SQLException e) {
              throw processException(e);
        }
    }

    /**
     * get a BinaryNullable from specified column of the resultSet (pColumnName)
     * and then convert it to byte[] which is an acceptable constructor argument
     * to the BinaryNullable class
     * 
     * @author Tim Faulkes
     * @param ColumnName - the name of the column to be retrieved from the resultSet
     */
    public BinaryNullable getBinaryNullable(String pColumnName) {
        try {
            //Blob theBlob = resultSet.getBlob(pColumnName);
            byte[] byteArray = resultSet.getBytes(pColumnName);

            if (byteArray == null || resultSet.wasNull()) {
                BinaryNullable result = new BinaryNullable();
                result.setIsNull(true);
                return result;
            }

            else {
                // byte[] byteArray = theBlob.getBytes(1, (int)theBlob.length());
                return new BinaryNullable(byteArray);
            }
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * get a BinaryData from specified column of the resultSet (ColumnID)
     * and then convert it to byte[] which is an acceptable constructor argument
     * to the BinaryNullable class
     * 
     * @author Tim Faulkes
     * @param ColumnID - the index of the column to be retrieved from the resultSet
     */
    public BinaryData getBinaryData(int ColumnID) {
        try {

            // Blob theBlob = resultSet.getBlob(ColumnID);
            byte[] byteArray = resultSet.getBytes(ColumnID);

            if (byteArray == null || resultSet.wasNull()) {
                return new BinaryData();
            }

            else {
                //byte[] byteArray = theBlob.getBytes(1, (int)theBlob.length());
                return new BinaryData(byteArray);
            }

        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * get a BinaryData from specified column of the resultSet (pColumnName)
     * and then convert it to byte[] which is an acceptable constructor argument
     * to the BinaryNullable class
     * 
     * @author Tim Faulkes
     * @param ColumnName - the name of the column to be retrieved from the resultSet
     */
    public BinaryData getBinaryData(String pColumnName) {
        try {
            //Blob theBlob = resultSet.getBlob(pColumnName);
            byte[] byteArray = resultSet.getBytes(pColumnName);

            if (byteArray == null || resultSet.wasNull()) {
                return new BinaryData();
            }

            else {
                // byte[] byteArray = theBlob.getBytes(1, (int)theBlob.length());
                return new BinaryData(byteArray);
            }
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public Object getObject(int ColumnID) {
        try {
            return resultSet.getObject(ColumnID);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    public Object getObject(String ColumnName) {
        try {
            return resultSet.getObject(ColumnName);
        } catch (SQLException e) {
          throw processException(e);
        }
    }

    /**
     * Package visible method to retrieve the underlying result set. This is needed for the db connection manager to
     * function properly.
     */
    ResultSet getResultSet() {
      return this.resultSet;
    }
   
    private RuntimeException processException(Exception e) {
        UsageException errorVar = new UsageException(e.getMessage(), SP_ER_USER, SP_ER_PARAMETERERROR, e);
        ErrorMgr.addError(errorVar);
        throw errorVar;
    }
    private RuntimeException processException(String message, Exception e) {
        UsageException errorVar = new UsageException(message, SP_ER_USER, SP_ER_PARAMETERERROR, e);
        ErrorMgr.addError(errorVar);
        throw errorVar;
    }
}
TOP

Related Classes of GenericDBMS.ResultSetHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.