/* 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 javax.swing.table.*; /** An implementation of {@link LineProvider} that provides data lines for saving * from a {@link javax.swing.table.TableModel}</a> object. * <p>The easiest way to save your CSV data using this format is to use the * {@link CsvManager#saveTableModel(Object,TableModel) CsvManager.saveTableModel} method. * You can get a <code>TableModel</code> from a {@link javax.swing.JTable} using the * {@link javax.swing.JTable#getModel JTable.getModel} method.</p> * <p><code>TableModelLineProvider</code> is designed to be subclassed. You can change * the default implementation by calling the * {@link com.ricebridge.csvman.CsvManagerStore#setTableModelLineProviderClass CsvManagerStore.setTableModelLineProviderClass} * method, and providing a subclass of * <code>TableModelLineProvider</code>. {@link CsvManagerStore} can be accessed * using {@link CsvManager#getCsvManagerStore}.</p> * <p>The <b><a href="TableModelLineProvider.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 ResultSetLineProvider * @see BeanLineProvider */ public class TableModelLineProvider extends CustomLineProvider { // static /** Save the {@link javax.swing.table.TableModel TableModel} column names as the first line of the CSV file. * (name for {@link CsvSpec#setProperty CsvSpec.setProperty}: <code>TableModel.saveHeaders</code>). */ public static final String PROP_TableModel_saveHeaders = "TableModel.saveHeaders"; /** Default value of <code>TableModel.saveHeaders</code> (<code>false</code>). */ public static final boolean DEFAULT_TableModel_saveHeaders = false; // protected /** Save the column headers to the CSV file. */ protected boolean iSaveHeaders = DEFAULT_TableModel_saveHeaders; /** The {@link javax.swing.table.TableModel} that the data comes from. */ protected TableModel iTableModel = 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; /** Current line. */ protected long iLineIndex = 0; // constructors /** Create uninitialised for use with {@link #setTableModel}. */ public TableModelLineProvider() { // init with setTableModel } /** Create initialised. See {@link #setTableModel} for details. * @param pTableModel <code>TableModel</code> providing data * @param pSaveHeaders Save the <code>TableModel</code> headers as first line */ public TableModelLineProvider( TableModel pTableModel, boolean pSaveHeaders ) { setTableModel( pTableModel, pSaveHeaders ); } // CustomLineProvider methods /** Handle property settings for loading data from a {@link javax.swing.table.TableModel TableModel}. * <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,TableModel,boolean) CsvManager.save(File, TableModel, 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_TableModel_saveHeaders}.</p> * * @see LineProvider#setCsvSpec * @see #PROP_TableModel_saveHeaders */ protected void setCsvSpecImpl( CsvSpec pCsvSpec ) throws Exception { iSaveHeaders = pCsvSpec.getBooleanProperty( PROP_TableModel_saveHeaders ); } /** Start the saving process. * @see LineProvider#startProcess() */ public void startProcessImpl() throws Exception { iFirstLine = true; iLineIndex = 0; } /** Return <code>true</code> if {@link javax.swing.table.TableModel TableModel} contains more rows. */ public boolean hasNextLineImpl() throws Exception { boolean hasNextLine = false; if( iSaveHeaders && iFirstLine ) { hasNextLine = true; } else { hasNextLine = ( iLineIndex < iTableModel.getRowCount() ); } return hasNextLine; } /** Return the current row of the {@link javax.swing.table.TableModel TableModel} as a <code>String[]</code> array. */ public String[] nextLineImpl() throws Exception { String[] line = null; if( iSaveHeaders && iFirstLine ) { line = iHeaders; iFirstLine = false; } else { line = new String[iFieldCount]; for( int fI = 0; fI < iFieldCount; fI++ ) { line[fI] = String.valueOf( iTableModel.getValueAt( (int) iLineIndex, fI ) ); } iLineIndex++; } return line; } // public methods /** Set the {@link javax.swing.table.TableModel} providing data to save. * <p>The default number of fields per line is taken from * {@link javax.swing.table.TableModel#getColumnCount TableModel.getColumnCount}</a> * and the headers (output as the first line when {@link #PROP_TableModel_saveHeaders} is <code>true)</code>, * are taken from {@link javax.swing.table.TableModel#getColumnName TableModel.getColumnName}. * </p> * @param pTableModel <code>TableModel</code> providing data * @param pSaveHeaders Save the <code>TableModel</code> headers as first line */ public void setTableModel( TableModel pTableModel, boolean pSaveHeaders ) { iTableModel = (TableModel) Internal.null_arg( pTableModel ); iSaveHeaders = iSaveHeaders || pSaveHeaders; iFieldCount = iTableModel.getColumnCount(); if( iSaveHeaders && 0 < iFieldCount ) { iHeaders = new String[ iFieldCount ]; for( int cI = 0; cI < iFieldCount; cI++ ) { iHeaders[cI] = iTableModel.getColumnName( cI ); } } else { iSaveHeaders = false; } } }