/* Copyright (c) 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;


/** Extend this class to create your own {@link LineProvider}.
 *    <p>You can export your data to CSV by overriding and implementing the methods in this class.
 *  You can do this when your source data must be accessed in a specific way and you need to control
 *  the exact data that is output. The basic idea is that you implement the {@link #hasNextLineImpl} and 
 *  {@link #nextLineImpl nextLineImpl} methods. These are called each time a line of CSV data is to be saved.
 *  You then return a <code>String[]</code> array containing your own data that <i>CSV Manager</i>
 *  will output as the fields of the CSV data line.</p>
 *    <p>Here's a very simple example. This <code>LineProvider</code> just creates a set of numbers to use
 *  as a data set. In your own projects, you'll probably source the data from a database or XML file, or other
 *  data storage system.</p>
 *  <pre><!--code-[-->
 *  public static class NumbersLineProvider extends CustomLineProvider {
 *    private int line = 0;
 *      
 *    protected boolean hasNextLineImpl() throws Exception {
 *      return line < 11;
 *    }
 *  
 *    protected String[] nextLineImpl() throws Exception {
 *      line++;
 *      return new String[] {""+line, ""+(10*line) };
 *    }   
 *  }
 *  <!--code-]--></pre>
 *    <p>You can see from this code that instead of implementing the public 
 *  {@link LineProvider#hasNextLine LineProvider.hasNextLine} and
 *  {@link LineProvider#nextLine LineProvider.nextLine}
 *  methods directly, you implement the protected {@link #hasNextLineImpl hasNextLineImpl} 
 *  and {@link #nextLineImpl nextLineImpl} methods. This insulates you from
 *  API changes and also provides an extra layer of error checking. 
 *  Also, <code>CustomLineProvider</code> provides default
 *  implementations for most of the methods of <code>LineProvider</code>, 
 *  so <code>hasNextLineImpl</code> and <code>nextLineImpl</code> are the only ones
 *  you need to worry about.</p>
 *    <p>Here's how you actually use this class:</p>
 *  <pre><!--code-[-->
 *    CsvManager           csvman = new CsvManager();
 *    NumbersLineProvider  nlp    = new NumbersLineProvider();
 *    csvManager.save( "output-file.csv", nlp );
 *  <!--code-]--></pre>
 *    <p>You just create a new instance of <code>NumbersLineProvider</code>, 
 *  and then pass it to {@link CsvManager}.</p>
 *    <p>When using custom <code>LineProviders</code>, the only thing that is
 *  different from the normal <code>save</code> methods is that you do not pass in the data to the <code>save</code> method. 
 *  You have to initialise your {@link LineProvider} with the data first.
 *    <p>For more information about implementing your own <code>LineProviders</code>, 
 *  see the {@link LineProvider} interface documentation. Also, take a look at the other methods
 *  you can implement:</p>
 *    <ul><li>{@link #setCsvSpecImpl setCsvSpecImpl}</li> 
 *        <li>{@link #setLineSpecImpl setLineSpecImpl}</li> 
 *        <li>{@link #startProcessImpl startProcessImpl}</li> 
 *        <li>{@link #endProcessImpl endProcessImpl}</li></ul>
 *    <p>Note: You can implement the {@link LineProvider} interface directly if you need to. 
 *  The danger is that your implementation may not remain compatible with future versions of
 *  <i>CSV Manager</i>. And you lose all the extra error-handling.
 *  So it's better to stick with extending <code>CustomLineProvider</code> if you can.</p>
 *    <p>Finally, if you want to load data with custom processing, see {@link LineListener}.</p>  
 *    <p>The <b><a href="CustomLineProvider.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>
 *  
 *  @since 1.2.1
 *  @see LineProvider
 *  @see LineProviderSupportImpl
 *  @see BasicLineProvider
 *  @see CsvManager
 *  @see CsvManagerException
 */
public abstract class CustomLineProvider extends LineProviderSupportImpl {

  // protected methods

  /** Set the current {@link CsvSpec} used for saving CSV files.
   *    <p>You can implement this method when you extend <code>CustomLineProvider</code>, 
   *  but it is not required.</p> 
   *    <p>The <code>CsvSpec</code> controls the CSV loading and saving process. It contains a
   *  number of settings such as the data field and line separators. You can also
   *  set your own custom settings using the {@link CsvSpec#setProperty CsvSpec.setProperty} method.
   *  You can then access these settings inside your own {@link LineProvider} 
   *  using the <code>CsvSpec</code> object passed into this method.</p>
   *    <p>This method is called before {@link #setLineSpecImpl setLineSpecImpl} is called.</p>
   *  @param pCsvSpec {@link CsvSpec} object
   *  @see CsvSpec
   *  @see #setLineSpecImpl setLineSpecImpl
   */
  protected void setCsvSpecImpl( CsvSpec pCsvSpec ) throws Exception {
    // default does nothing
  }


  /** Set the current {@link LineSpec} used for interpreting CSV data fields.
   *    <p>You can implement this method when you extend <code>CustomLineProvider</code>, 
   *  but it is not required.</p> 
   *    <p>The <code>LineSpec</code> controls the conversion of internal data into individual CSV data fields.
   *  Whereas {@link CsvSpec} controls the entire process, <code>LineSpec</code> only applies to each data field.
   *  In the current version of <i>CSV Manager</i> (1.2), <code>LineSpec</code> is used to load and save Java Beans, 
   *  by providing the <code>get</code> and <code>set</code> method names for each data field. 
   *  See {@link BeanLineProvider} for more details.</p>
   *    <p>You can subclass <code>LineSpec</code> to add your own
   *  data field specific information for your own custom {@link LineProvider LineProviders}.
   *  You can then access these settings inside your own <code>LineProvider</code>
   *  using the <code>LineSpec</code> object passed into this method.</p>
   *    <p>This method is called after {@link #setCsvSpecImpl setCsvSpecImpl} is called.</p>
   *  @param pLineSpec {@link LineSpec} object
   *  @see LineSpec
   *  @see #setCsvSpecImpl setCsvSpecImpl
   *  @see BeanLineProvider
   */
  protected void setLineSpecImpl( LineSpec pLineSpec ) throws Exception {
    // default does nothing
  }


  /** Implement this method to receive notification that the saving of CSV data is about to start. 
   *    <p>You can implement this method when you extend <code>CustomLineProvider</code>, 
   *  but it is not required.</p> 
   *    <p>You can use this method to initialise any resource you need to process the CSV data.
   *  For example you can open a database connection to retrieve the data as it is saved.</p>
   *    <p>This method is called <i>after</i> {@link #setCsvSpecImpl setCsvSpecImpl} and
   *  {@link #setLineSpecImpl setLineSpecImpl}.
   *  @see #endProcessImpl endProcessImpl
   */
  protected void startProcessImpl() throws Exception {
    // empty implementation
  }


  /** Implement this method to let <i>CSV Manager</i> know that there is another line of data to save.
   *    <p>This method must be implemented when you extend <code>CustomLineProvider</code>.</p> 
   *    <p>Return <code>true</code> from this method so long as you have more data lines to save.</p>
   *  @see LineProvider#hasNextLine LineProvider.hasNextLine
   *  @see #nextLineImpl nextLineImpl
   */
  protected abstract boolean hasNextLineImpl() throws Exception;


  /** Implement this method to supply each data line as it is saved.
   *    <p>This method must be implemented when you extend <code>CustomLineProvider</code>.</p> 
   *    <p>This method is where you will do the main work of providing the CSV data. Each time this
   *  method is called you will need to provide a new line of CSV data as a <code>String[]</code> array.</p>
   *    <p><b>Error Handling:</b> What happens when you cannot provide the line data for some reason?
   *  For example your database connection may fail. In this case, all you have to do is throw an
   *  <code>Exception</code> to let <i>CSV Manager</i> know about the problem. But note that if the
   *  {@link CsvSpec#setIgnoreBadLines CsvSpec.setIgnoreBadLines} setting is <code>true</code>, then
   *  <i>CSV Manager</i> will not stop asking you for more data lines until you also return 
   *  <code>false</code> from {@link #hasNextLineImpl}.</p> 
   *  @see LineProvider#nextLine LineProvider.nextLine
   *  @see #hasNextLineImpl hasNextLineImpl
   */
  protected abstract String[] nextLineImpl() throws Exception;


  /** Implement this method to receive notification that the saving of CSV data has ended.
   *    <p>You can implement this method when you extend <code>CustomLineProvider</code>, 
   *  but it is not required.</p> 
   *    <p>You can use this method to close any open resources that were used to handle the
   *  CSV data. For example you can close any open database connections.</p>
   *    <p>This method is called <i>last</i>, after all {@link #hasNextLineImpl hasNextLineImpl}
   *  and {@link #nextLineImpl nextLineImpl} calls have been made.</p>
   *  @see #startProcessImpl startProcessImpl
   */
  protected void endProcessImpl() throws Exception {
    // empty implementation
  }

}
Syntax Highlighting created using the com.Ostermiller.Syntax package.
Wednesday, November 08 2006 at 19:54