/* Copyright (c) 2003-2006 Ricebridge. All Rights Reserved.
 *
 * This file is available under the terms and conditions of the
 * Ricebridge "Open Source API" policy; Ricebridge grants use of this
 * copyrighted work under the terms of a BSD-style license only. See
 * http://www.opensource.org/licenses/bsd-license.php for more
 * information.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *  - Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above
 *  copyright notice, this list of conditions and the following
 *  disclaimer in the documentation and/or other materials provided
 *  with the distribution.
 *
 *  - Neither the name of the Ricebridge nor the names of its
 *  contributors may be used to endorse or promote products derived
 *  from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 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 com.ricebridge.csvman;


import org.jostraca.util.Internal;
import org.jostraca.util.Standard;


import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

/** An implementation of {@link LineProvider} that provides data lines for saving
 *  from a {@link java.sql.ResultSet ResultSet} object.
 *    <p>The easiest way to save your CSV data using this format is to use the 
 *  {@link CsvManager#saveResultSet(Object,ResultSet) CsvManager.saveResultSet} method.</p>
 *    <p><code>ResultSetLineProvider</code> is designed to be subclassed. You can change
 *  the default implementation by calling the 
 *  {@link CsvManagerStore#setResultSetLineProviderClass CsvManagerStore.setResultSetLineProviderClass}
 *  method, and providing a subclass of 
 *  <code>ResultSetLineProvider</code>. {@link CsvManagerStore} can be accessed 
 *  using {@link CsvManager#getCsvManagerStore}.</p>
 *    <p>The <b><a href="ResultSetLineProvider.java.html">Source Code</a></b> of this Java class 
 *    is available under a <a href="http://www.opensource.org/licenses/bsd-license.php">BSD-style license</a>.</p>
 *
 *  @see LineProvider
 *  @see CustomLineProvider
 *  @see BasicLineProvider 
 *  @see AsListsLineProvider 
 *  @see TableModelLineProvider 
 *  @see BeanLineProvider 
 */
public class ResultSetLineProvider extends CustomLineProvider {

  // static

  /** Save the {@link java.sql.ResultSet ResultSet} column names as the first line of the CSV file.
   *  (name for {@link CsvSpec#setProperty CsvSpec.setProperty}: <code>ResultSet.saveHeaders</code>). 
   */
  public static final String PROP_ResultSet_saveHeaders = "ResultSet.saveHeaders";

  /** Default value of <code>ResultSet.saveHeaders</code> (<code>false</code>). */
  public static final boolean DEFAULT_ResultSet_saveHeaders = false;




  // protected

  /** Save the column headers to the CSV file. */
  protected boolean iSaveHeaders = DEFAULT_ResultSet_saveHeaders;

  /** The {@link java.sql.ResultSet ResultSet} that the data comes from. */
  protected ResultSet iResultSet = null;

  /** The column headers */
  protected String[] iHeaders = null;

  /** Flag to indicate processing of the first line. */
  protected boolean iFirstLine = true;

  /** Number of data fields per line. */
  protected int iFieldCount = 0;




  // constructors

  /** Create uninitialised for use with {@link #setResultSet}. */
  public ResultSetLineProvider() {
    // init with setResultSet
  }



  // CustomLineProvider methods

  /** Handle property settings for loading data from a {@link java.sql.ResultSet ResultSet}. 
   *    <p>You can change these using {@link CsvSpec}.</p>
   *    <p>Compatibility note: the correct way to change the settings for a {@link LineProvider} is by using the
   *  {@link CsvSpec#setProperty CsvSpec.setProperty} method. <i>CSV Manager 1.1</i> also allowed you to set certain
   *  settings as <code>save</code> method parameters (for example: <code>pHasHeaders</code> 
   *  in {@link CsvManager#save(File,ResultSet,boolean) CsvManager.save(File, ResultSet, boolean)}. 
   *  These parameters will be removed in <i>CSV Manager 2.0</i>, so you should not use them anymore. 
   *  They are only retained for compatibility with <i>CSV Manager 1.1</i>.</p>
   *    <p>The property you can use here is: {@link #PROP_ResultSet_saveHeaders}.</p>
   *
   *  @see LineProvider#setCsvSpec
   *  @see #PROP_ResultSet_saveHeaders
   */
  protected void setCsvSpecImpl( CsvSpec pCsvSpec ) throws Exception {
    iSaveHeaders = pCsvSpec.getBooleanProperty( PROP_ResultSet_saveHeaders );
  }


  /** Start the saving process. 
   *  @see LineProvider#startProcess()
   */
  protected void startProcessImpl() throws Exception {
    iFirstLine = true;
  }


  /** Return <code>true</code> if {@link java.sql.ResultSet#next ResultSet.next} returns <code>true</code>. */
  protected boolean hasNextLineImpl() throws Exception {
    if( iSaveHeaders && iFirstLine ) {
      return true;
    }
    else {
      try {
        return iResultSet.next();
      }
      catch( Exception e ) {
        throw new CsvManagerException( CsvManagerException.CODE_resultset_next, 
                                       new String[] { "resultset", String.valueOf(iResultSet) }, e );
      }
    }
  }


  /** Return current {@link java.sql.ResultSet ResultSet} row as a <code>String[]</code> array. */
  protected String[] nextLineImpl() throws Exception {
    String[] line = new String[iFieldCount];
    for( int fI = 1; fI <= iFieldCount; fI++ ) {
      line[fI-1] = getFieldAsString(fI);
    }
    iFirstLine = false;
    return line;
  }


  /** End the saving process. 
   *  @see LineProvider#endProcess()
   */
  protected void endProcessImpl() throws Exception {
    // do nothing
  }




  // public methods

  /** Set the <code>ResultSet</code> that provides the data to save. 
   *    <p>The default number of fields per line is taken from 
   *  {@link java.sql.ResultSetMetaData#getColumnCount ResultSetMetaData.getColumnCount}
   *  and the headers (output as the first line when {@link #PROP_ResultSet_saveHeaders} is <code>true)</code>, 
   *  are taken from
   *  {@link java.sql.ResultSetMetaData#getColumnName ResultSetMetaData.getColumnName}.</p>
   *  @param pResultSet  <code>ResultSet</code> providing data
   *  @param pSaveHeaders Save the <code>ResultSet</code> headers as first line (old parameter, use {@link #PROP_ResultSet_saveHeaders} instead)
   */
  public void setResultSet( ResultSet pResultSet, boolean pSaveHeaders ) {
    iResultSet = (ResultSet) Internal.null_arg( pResultSet );

    ResultSetMetaData rsmd = null;
    try {
      rsmd = iResultSet.getMetaData();
    }
    catch( Exception e ) {
      throw new CsvManagerException( CsvManagerException.CODE_resultset_getmetadata, 
                                     new String[] { "resultset", String.valueOf(iResultSet) }, e );
    }

    try {
      iFieldCount = rsmd.getColumnCount();
    }
    catch( Exception e ) {
      throw new CsvManagerException( CsvManagerException.CODE_rsmd_getcolcount, 
                                     new String[] { "resultset", String.valueOf(iResultSet), 
                                                    "resultsetmetadata", String.valueOf(rsmd)}, e );
    }


    iSaveHeaders = iSaveHeaders || pSaveHeaders;
    if( iSaveHeaders && -1 < iFieldCount) {
      iHeaders = new String[ iFieldCount + 1 ];
      try {
        for( int cI = 1; cI <= iFieldCount; cI++ ) {
          iHeaders[cI] = rsmd.getColumnName( cI );
        }
      }
      catch( Exception e ) {
        throw new CsvManagerException( CsvManagerException.CODE_rsmd_getcolname, 
                                       new String[] { "resultset", String.valueOf(iResultSet), 
                                                      "resultsetmetadata", String.valueOf(rsmd)}, e );
      }
    }
    else {
      iSaveHeaders = false;
    }
  }




  // protected

  /** Get the <code>String</code> value of a {@link java.sql.ResultSet ResultSet} field. */
  protected String getFieldAsString( int pFieldIndex ) {
    String field = Standard.EMPTY;
    if( iSaveHeaders && iFirstLine ) {
      field = iHeaders[ pFieldIndex ];
    }
    else {
      try {
        field = String.valueOf( iResultSet.getObject( pFieldIndex ) );
      }
      catch( Exception e ) {
        throw new CsvManagerException( CsvManagerException.CODE_resultset_getobject, 
                                       new String[] { "resultset", String.valueOf(iResultSet), 
                                                      "fieldindex", String.valueOf(pFieldIndex-1) }, e );
      }
    }

    return field;
  }

}
Syntax Highlighting created using the com.Ostermiller.Syntax package.
Monday, October 30 2006 at 11:33