/* 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 java.util.*; import java.sql.*; /** An implementation of {@link LineListener} that inserts loaded data lines * into a {@link java.sql.ResultSet ResultSet}</a>. * <p>You can then use this <code>ResultSet</code> directly to retrieve the data. See {@link CsvResultSet} * for more details. The easiest way to get a <code>ResultSet</code> of your CSV data is to use the * {@link CsvManager#loadResultSet(Object) CsvManager.loadResultSet} method.</p> * <p><code>ResultSetLineListener</code> is designed to be subclassed. You can change * the default implementation by calling the * {@link CsvManagerStore#setResultSetLineListenerClass CsvManagerStore.setResultSetLineListenerClass} * method, and providing a subclass of * <code>ResultSetLineListener</code>. {@link CsvManagerStore} can be accessed * using {@link CsvManager#getCsvManagerStore}.</p> * <p>The <b><a href="ResultSetLineListener.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 LineListener * @see CustomLineListener * @see BasicLineListener * @see AsListsLineListener * @see TableModelLineListener * @see BeanLineListener */ public class ResultSetLineListener extends HeadersListenerSupport { // static /** Specify that the first row of data is a header line containing the names of the data fields. * (name for {@link CsvSpec#setProperty CsvSpec.setProperty}: <code>ResultSet.dataHasHeaders</code>). */ public static final String PROP_ResultSet_dataHasHeaders = "ResultSet.dataHasHeaders"; /** Default value of <code>ResultSet.dataHasHeaders</code> (<code>false</code>). */ public static final boolean DEFAULT_ResultSet_dataHasHeaders = false; // protected /** <code>ResultSet</code> implementation class used to create new instances. */ protected Class iCsvResultSetClass = CsvResultSet.class; /** <code>List</code> of <code>String[]</code> arrays holding data lines. */ protected ArrayList iData = new ArrayList(); /** Number of data fields. */ protected int iNumFields = 0; /** When <code>true</code>, the first line of CSV data should be a header line specifying the data field names. */ protected boolean iDataHasHeaders = DEFAULT_ResultSet_dataHasHeaders; // CustomLineListener methods /** Handle property settings for loading data in 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 LineListener} 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>load</code> method parameters (for example: <code>pHasHeaders</code> * in {@link CsvManager#loadResultSet(File,boolean) CsvManager.loadResultSet(File, 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_dataHasHeaders}.</p> * @see LineListener#setCsvSpec * @see #PROP_ResultSet_dataHasHeaders */ protected void setCsvSpecImpl( CsvSpec pCsvSpec ) throws Exception { iNumFields = pCsvSpec.getNumFields(); iDataHasHeaders = pCsvSpec.getBooleanProperty( PROP_ResultSet_dataHasHeaders ); } /** Start the loading process. * @see LineListener#startProcess() */ protected void startProcessImpl() throws Exception { iData = new ArrayList(); } /** Add the data line <code>String[]</code> array to the list of {@link java.sql.ResultSet} rows. */ protected BadLine handleLineImpl( String[] pLine, int pNumFields, long pLineNumber, String pOriginalLine ) throws Exception { iData.add( pLine ); return null; // always accept data line } /** End the loading process. * @see LineListener#endProcess() */ protected void endProcessImpl() throws Exception { if( null == iData ) { iData = new ArrayList(); } } // public methods /** Get a <code>ResultSet</code> instance that presents the CSV data. */ public ResultSet getResultSet() { CsvResultSet csvrs = null; try { csvrs = (CsvResultSet) iCsvResultSetClass.newInstance(); } catch( Exception e ) { throw new CsvManagerException( CsvManagerException.CODE_csvrs_new, new String[] { "class", null==iCsvResultSetClass?"null":iCsvResultSetClass.getName() }, e ); } // iHasHeaders defined in HeadersListenerSupport csvrs.setData( iData, iHasHeaders || iDataHasHeaders, iNumFields ); return csvrs; } /** Use your own subclass of {@link CsvResultSet} for loading CSV data. * <p>You may subclass <code>CsvResultSet</code> so that the CSV data is loaded into your own <code>ResultSet</code>. * You will need to provide an empty constructor so that the <code>newInstance</code> method will work. You * must also provide, via this method, the class of your <code>ResultSet</code>. Do this like so:<pre> * csvManager.getCsvManagerStore() * .getResultSetLineListener().setCsvResultSetClass( MyCsvResultSet.class ); * </pre></p> * <p>If subclassing does not fit with your requirements, consider implementing your own variation of * {@link CsvResultSet} <a href="CsvResultSet.java.html">(source)</a> and * {@link ResultSetLineListener} <a href="ResultSetLineListener.java.html">(source)</a> * based on the source code provided as part of this API documentation. </p> * <p><b>NOTE:</b> this method is deprecated. To provide your own version of {@link CsvResultSet}, please * subclass <code>ResultSetLineListener</code> directly and set the * {@link ResultSetLineListener#iCsvResultSetClass} member variable to your own * subclass of <code>CsvResultSet</code>.</p> * @param pCsvResultSetClass class of <code>CsvResultSet</code> subclass * @see CsvResultSet */ public void setCsvResultSetClass( Class pCsvResultSetClass ) { iCsvResultSetClass = (Class) Internal.null_arg( pCsvResultSetClass ); } }