/* 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; /** Use this interface to create custom CSV data loaders. * <p>This callback interface allows you to handle each data line separately as it is loaded. * To implement this interface, please extend {@link CustomLineListener}, as that will help keep your code * compatible with future versions.</p> * <p>To use a <code>LineListener</code>, call the {@link CsvManager#load(Object, LineListener)} or * {@link CsvManager#load(Object, LineSpec, LineListener)} methods.</p> * <p>When you pass an instance of <code>LineListener</code> to {@link CsvManager}, it will * call the {@link #handleLine handleLine} method each time a data line is loaded. * The string values of the data fields are provided as * a <code>String[]</code> array. When a badly formatted line is encountered, * the {@link #handleBadLine handleBadLine} method is called instead.</p> * <p>As <code>CsvManager</code> loads the CSV data, it calls the * methods of the <code>LineListener</code> in a defined sequence:</p> * <ol><li>{@link #setCsvSpec setCsvSpec}</li> * <li>{@link #setLineSpec setLineSpec}</li> * <li>{@link #startProcess startProcess}</li> * <li>{@link #handleLine handleLine}</li> * <li>{@link #endProcess endProcess}</li></ol> * <p>The {@link #handleLine handleLine} method is called once for each line in the CSV file.</p> * <p>When writing your own <code>LineListener</code>, the easiest way to get started is to review the source code for the * existing <code>LineListeners</code> used by <code>CsvManager</code>. <code>CsvManager</code> uses <code>LineListeners</code> * internally for all data loading operations. * The {@link BasicLineListener} is a very simple example and a good place to start. * Here is the full list of standard <code>LineListeners</code>:</p> * <ul><li>{@link BasicLineListener}</li> * <li>{@link AsListsLineListener}</li> * <li>{@link TableModelLineListener}</li> * <li>{@link ResultSetLineListener}</li> * <li>{@link BeanLineListener}</li></ul> * <p>Note: you may assume in your implementation that no parameters are <code>null</code>.</p> * <p><b>Error Handling</b><br /> * The <code>handleLine</code> method can return a {@link BadLine} object that describes a semantically incorrect * line of data. This allows you to perform validation against the input data. You can also return a <code>BadLine</code> when database * access fails, or some other problem occurs. When everything is OK, there is no need to return a <code>BadLine</code>, * simply return <code>null</code> from the <code>handleLine</code> method. You can also allow <code>Exceptions</code> to pass up * to the <code>CustomLineListener</code> class, without handling them yourself. * In this case <code>CsvManager</code> will handle them for you, either * halting the load operation, or creating a <code>BadLine</code> and storing it, depending on the value of the * {@link CsvSpec#setIgnoreBadLines CsvSpec.setIgnoreBadLines} setting.</p> * <p>If you set <code>setIgnoreBadLines</code> to <code>true</code> then loading of CSV data will continue * even when badly formatted data lines are encountered. If this setting is <code>false</code> (the default), then loading is halted * and a {@link CsvManagerException} <code>(CODE_bad_line)</code> is thrown <i>after</i> <code>handleBadLine</code> is called.</p> * <p><b>Important</b><br /> * In order to ensure the greatest compatibility with future releases and to take advantage of additional error handling * functionality, please implement your <code>LineListener</code> by extending the abstract {@link CustomLineListener} class. * This class ensures that all data you receive is well-formed (no <code>nulls</code>), and also creates standard * exceptions when problems do occur.</p> * <p>Compatibility Note: <i>CSV Manager 1.1</i> used {@link LineListenerSupport} * instead of <code>CustomLineListener</code>. Existing code will still work with this base class, but you should * always use <code>CustomLineListener</code> for new code.</p> * <p>The <b><a href="LineListener.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 CustomLineListener * @see BasicLineListener * @see CsvManager * @see CsvManagerException */ public interface LineListener { /** Set the current {@link CsvSpec} settings. * <p>You can implement this method to get the values of the current settings, * and use them to modify your data handling. For example, {@link TableModelLineListener} * uses the custom property <code>TableModel.editable</code> to make any * {@link javax.swing.table.TableModel TableModels} that it returns editable. You can easily use your own * custom properties by calling the {@link CsvSpec#setProperty(String, String) CsvSpec.setProperty} method.</p> * <p>Note: to actually set the {@link CsvSpec} object, you use {@link CsvManager#setCsvSpec CsvManager.setCsvSpec}.</p> * <p><b>Implement by overriding {@link CustomLineListener#setCsvSpecImpl CustomLineListener.setCsvSpecImpl}.</b></p> * @param pCsvSpec <code>CsvSpec</code> object */ public void setCsvSpec( CsvSpec pCsvSpec ); /** Set the current {@link LineSpec} settings. * <p>You can implement this method to get the current <code>LineSpec</code> you specified for the data you are loading. * The <code>LineSpec</code> provides additional information about each data field. For example, {@link BeanLineListener} * uses the {@link LineSpec#getFieldNames field names} metadata to determine the right get and set methods for * each data field.</p> * <p>You can add your own metadata for use by {@link CustomLineListener CustomLineListeners} * by subclassing <code>LineSpec</code> and adding appropriate methods to return your custom metadata.</p> * <p><b>Implement by overriding {@link CustomLineListener#setLineSpecImpl CustomLineListener.setLineSpecImpl}.</b></p> * @param pLineSpec <code>LineSpec</code> object */ public void setLineSpec( LineSpec pLineSpec ); /** Called just before loading of the CSV data starts. * <p>You should use this method to initialise any data receivers in your <code>LineListener</code>. * For example, you can initialise any database connections or other resources that you need to use to process the data.</p> * <p><b>Implement by overriding {@link CustomLineListener#startProcessImpl CustomLineListener.startProcessImpl}.</b></p> * @see #endProcess */ public void startProcess(); /** Implement this method to directly access the data for each line as it is parsed. * <p>The parameter <code>pLine</code> is a <code>String[]</code> that is normally * {@link CsvSpec#setNumFields setNumFields} in length. If fewer than * <code>pNumFields</code> columns are found in the current line, then * the remaining elements of <code>pLine</code> are empty strings. If more than * <code>pNumFields</code> columns are found, then <code>pLine</code> is a <code>String[]</code> array large enough to * contain all data fields found. In both cases, the parameter <code>pNumFields</code> * indicates the exact number of data fields found.</p> * <p>This method should return a {@link BadLine} object if the data in <code>pLine</code> * was invalid in some way. Data lines that cannot be parsed due to syntax errors are not sent to the * <code>LineListener</code> via this method. However, syntactically correct lines may still contain invalid data * and this should be indicated by returning a {@link BadLine} object describing the problem from this method. * Return <code>null</code> * if the data was acceptable. This return value is used to maintain internal bad line counts so that * the loading statistics are correct. The use of a return value rather than an <code>Exception</code> was chosen * for performance reasons. You may still throw a {@link java.lang.RuntimeException} from within this method * and {@link CsvManager} will record the error, passing on the <code>Exception</code> contained in * a {@link CsvManagerException} ({@link CsvManagerException#CODE_internal_exception CODE_internal_exception}, * or continuing to load data if {@link CsvManager#setIgnoreBadLines} is <code>true</code>.</p> * <p><b>Implement by overriding {@link CustomLineListener#handleLineImpl CustomLineListener.handleLineImpl}.</b></p> * * @param pLine line data as text * @param pNumFields number of data fields found * @param pLineNumber line number index, counting from 1 * @param pOriginalLine original line of data * @return <code>null</code> if line is OK, {@link BadLine} object if line was bad in some way */ public BadLine handleLine( String[] pLine, int pNumFields, long pLineNumber, String pOriginalLine ); /** Called when a badly formatted data line is encountered. * <p>This method is only called once (and data loading stops) * if {@link CsvManager#setIgnoreBadLines} is <code>false</code> (the default). * If {@link CsvManager#setIgnoreBadLines} is <code>true</code>, each badly formatted line is * sent to the <code>LineListener</code> implementation via this method.</p> * <p>The text of the badly formatted line is given by {@link BadLine#getOriginalLine} and * the parser error message (or other internal error) is given in the {@link BadLine#getErrorMsg}.</p> * <p>The error message description passed to this method is not suitable for non-technical users. To get a user-friendly message set * {@link CsvManager#setIgnoreBadLines} to <code>false</code> and call {@link CsvManagerException#toString} on any * {@link CsvManagerException}s that are thrown while loading CSV data.</p> * <p><b>Implement by overriding {@link CustomLineListener#handleBadLineImpl CustomLineListener.handleBadLineImpl}.</b></p> * @param pBadLine {@link BadLine} object describing problem */ public void handleBadLine( BadLine pBadLine ); /** Called just after loading of the CSV data ends. * <p>You should use this method to release any resources used by your <code>LineListener</code>.</p> * <p><b>Implement by overriding {@link CustomLineListener#endProcessImpl CustomLineListener.endProcessImpl}.</b></p> * @see #startProcess */ public void endProcess(); }