/* 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; } }