/* 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; /** An implementation of {@link LineListener} that inserts loaded data lines * into a {@link javax.swing.TableModel TableModel}</a>. * <p>You can then use this <code>TableModel</code> directly with a * {@link javax.swing.JTable JTable} to create a tabular display of your data.</a>. * The easiest way to get your CSV data as a <code>TableModel</code> is to use the * {@link CsvManager#loadTableModel(Object) CsvManager.loadTableModel} method.</p> * <p>You can find more information about the <code>TableModel</code> implementation here: {@link CsvTableModel}.</p> * <p><code>TableModelLineListener</code> is designed to be subclassed. You can change * the default implementation by calling the * {@link com.ricebridge.csvman.CsvManagerStore#setTableModelLineListenerClass CsvManagerStore.setTableModelLineListenerClass} * method, and providing a subclass of * <code>TableModelLineListener</code>. {@link CsvManagerStore} can be accessed * using {@link CsvManager#getCsvManagerStore}.</p> * <p>The <b><a href="TableModelLineListener.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 ResultSetLineListener * @see BeanLineListener */ public class TableModelLineListener 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>TableModel.dataHasHeaders</code>). */ public static final String PROP_TableModel_dataHasHeaders = "TableModel.dataHasHeaders"; /** Default value of <code>TableModel.dataHasHeaders</code>). */ public static final boolean DEFAULT_TableModel_dataHasHeaders = false; /** Specify that table cells can be edited * (name for {@link CsvSpec#setProperty CsvSpec.setProperty}: <code>TableModel.editable</code>). */ public static final String PROP_TableModel_editable = "TableModel.editable"; /** Default value of <code>TableModel.editable</code>). */ public static final boolean DEFAULT_TableModel_editable = false; // protected /** <code>TableModel</code> implementation class used to create new instances. */ protected Class iCsvTableModelClass = CsvTableModel.class; /** <code>TableModel</code> instance to hold CSV data */ protected CsvTableModel iCsvTableModel = null; /** Make the <code>TableModel</code> editable. See {@link #setEditable}. */ protected boolean iEditable = false; /** 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_TableModel_dataHasHeaders; /** When <code>true</code>, the {@link javax.swing.table.TableModel TableModel} returned will be editable. */ protected boolean iPropEditable = DEFAULT_TableModel_editable; // CustomListenerSupport methods /** Handle property settings for loading data into {@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 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#loadTableModel(File,boolean) CsvManager.loadTableModel(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 properties you can use here are: {@link #PROP_TableModel_dataHasHeaders} and * {@link #PROP_TableModel_editable}.</p> * @see LineListener#setCsvSpec * @see #PROP_TableModel_dataHasHeaders */ protected void setCsvSpecImpl( CsvSpec pCsvSpec ) throws Exception { iDataHasHeaders = pCsvSpec.getBooleanProperty( PROP_TableModel_dataHasHeaders ); iPropEditable = pCsvSpec.getBooleanProperty( PROP_TableModel_editable ); } /** Start the load process. * @see LineListener#startProcess() */ protected void startProcessImpl() throws Exception { try { iCsvTableModel = (CsvTableModel) iCsvTableModelClass.newInstance(); } catch( Exception e ) { throw new CsvManagerException( CsvManagerException.CODE_csvtm_new, new String[] { "class", null==iCsvTableModelClass?"null":iCsvTableModelClass.getName() }, e ); } iCsvTableModel.init(); iCsvTableModel.setHasHeaders( iDataHasHeaders || iHasHeaders ); iCsvTableModel.setEditable( iPropEditable || iEditable ); } /** Add the data line <code>String[]</code> array to the list of {@link javax.swing.table.TableModel} rows. */ protected BadLine handleLineImpl( String[] pLine, int pNumFields, long pLineNumber, String pOriginalLine ) throws Exception { iCsvTableModel.addLine( pLine, pNumFields ); return null; // always accept data line } // public methods /** The data cells of the first line of the CSV file may be column headers. * <p>When <code>pHasHeaders</code> is <code>true</code>, the first line of the CSV file * is considered to consist of column header names rather than normal data.</p> * <p>When <code>pHasHeaders</code> is <code>false</code>, the first line of the CSV file * is considered to be normal data and default column names are used.</p> * <p>In the case where there are no column names, or not enough column names, the default form * <i>Column X</i> is used, where <i>X</i> is the number of the column, counting from 1.</p> * <p>Compatibility note: please use {@link CsvSpec#setProperty CsvSpec.setProperty} to set * this setting instead of this method, which will be remove in <i>CSV Manager 1.2</i>. See * {@link #setCsvSpecImpl setCsvSpecImpl} for more details.</p> * @param pHasHeaders first line is header names * @see CsvTableModel#setHasHeaders(boolean) CsvTableModel.setHasHeaders * @see #setCsvSpecImpl setCsvSpecImpl */ public void setHasHeaders( boolean pHasHeaders ) { iHasHeaders = pHasHeaders; } /** Make the <code>TableModel</code> editable. * <p>When <code>true</code>, the method <code>TableModel</code> interface method * <a href="http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/table/TableModel.html#isCellEditable(int,%20int)" * >TableModel.isCellEditable(int, int)</a> * returns <code>true</code> for every table cell. This makes the <code>JTable</code> editable.</p> * <p>When <code>false</code>, the <code>JTable</code> is not editable. * @param pEditable make the <code>JTable</code> editable * @see CsvTableModel#setEditable */ public void setEditable( boolean pEditable ) { iEditable = pEditable; } /** Use your own subclass of {@link CsvTableModel} for loading CSV data. * <p>You may subclass <code>CsvTableModel</code> so that the CSV data is loaded into your own <code>TableModel</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>TableModel</code>. Do this like so:<pre> * csvManager.getCsvManagerStore() * .getTableModelLineListener().setCsvTableModelClass( MyCsvTableModel.class ); * </pre></p> * <p>If subclassing does not fit with your requirements, consider implementing your own variation of * {@link CsvTableModel} <a href="CsvTableModel.java.html">(source)</a> and * {@link TableModelLineListener} <a href="TableModelLineListener.java.html">(source)</a> * based on the source code provided as part of this API documentation. </p> * @param pCsvTableModelClass class of <code>CsvTableModel</code> subclass * @see CsvTableModel */ public void setCsvTableModelClass( Class pCsvTableModelClass ) { iCsvTableModelClass = (Class) Internal.null_arg( pCsvTableModelClass ); } /** Get the new {@link CsvTableModel} instance containing the CSV data. */ public CsvTableModel getCsvTableModel() { return iCsvTableModel; } }