/* Copyright (c) 2005 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.xmlman; /** Implement this interface by extending {@link RecordProviderSupport} to provide each data record for saving. * <p>This callback interface allows you to provide data records on demand so that they can be saved as * quickly as possible with minimal memory usage. This means that you can avoid storing all the data you want to * save in memory at the same time. For example, if you want to save data from a database to an XML file, you do not * have to load all the data at once, but can step through the {@link java.sql.ResultSet} and save each record directly. * See the <a href="http://www.ricebridge/com/products/xmlman/doc/examples/database/readme.htm">database example</a> * for more information.</p> * <p>Once you have created your own <code>RecordProvider</code>, you can use it by calling the <code>save</code> methods * of {@link XmlManager} that accept a <code>RecordProvider</code> as an argument, for example: * {@link XmlManager#save(File,RecordSpec,RecordProvider)}. <code>XmlManager</code> than starts to save the data and calls the * methods of the <code>RecordProvider</code> in a defined sequence:</p> * <ol><li>{@link #setXmlSpec setXmlSpec}</li> * <li>{@link #setFieldNames setFieldNames}</li> * <li>{@link #startProcess startProcess}</li> * <li>{@link #hasNextRecord hasNextRecord}</li> * <li>{@link #nextRecord nextRecord}</li> * <li>{@link #endProcess endProcess}</li></ol> * <p>The {@link #hasNextRecord hasNextRecord} and {@link #nextRecord nextRecord} methods are called * called in sequence, once for each data record.</p> * <p>When writing your own <code>RecordProvider</code>, the easiest way to get started is to review the source code for the * existing <code>RecordProviders</code> used by <code>XmlManager</code>. <code>XmlManager</code> uses <code>RecordProviders</code> * internally for all data saving operations. * The {@link StringArrayRecordProvider} is a very simple example and a good place to start.</p> * <p><b>Error Handling</b><br /> * If an error occurs when you are creating the data for the next record, * you can allow <code>Exceptions</code> to pass up to the support class, without handling them yourself. * In this case <code>XmlManager</code> will handle them for you, either * halting the save operation, or creating a <code>BadRecord</code> and storing it, depending on the value of the * {@link XmlSpec#setIgnoreBadRecords} setting.</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>RecordProvider</code> by extending the abstract {@link RecordProviderSupport} class. * This class creates standard exceptions when problems do occur.</p> * <p>The <b><a href="RecordProvider.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> */ public interface RecordProvider { // public methods /** Set the current {@link XmlSpec} 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 TableModelRecordProvider} * uses the custom property <code>TableModel.saveHeaders</code> to output the headers of the * {@link javax.swing.table.TableModel TableModel} that it is saving as the first data record. * You can easily use your own * custom properties by calling the {@link XmlSpec#setProperty XmlSpec.setProperty} method.</p> * @param pXmlSpec <code>XmlSpec</code> object */ public void setXmlSpec( XmlSpec pXmlSpec ); /** Set the field names of the primary {@link RecordSpec}. * <p>You can implement this method to get the list of field names that * apply to the data. This is useful when you need to identify the data fields * for additional functionality. For example, the {@link BeanRecordProvider} class uses the field * names to determine the correct <i>get</i> methods to call.</p> * <p>Note: if no field names are provided in the primary <code>RecordSpec</code>, then this method is <i>not</i> called.</p> * <p>When you extend {@link RecordProviderSupport} to implement the <code>RecordProvider</code> interface, * you gain access to the protected instance variable <code>iFieldNames</code>, which will contain any * field names if provided, or otherwise be empty. You can override the * {@link RecordProviderSupport#setFieldNamesImpl} method to handle the field names in a different manner.</p> * <p>If more than one <code>RecordSpec</code> was specified, then only the field names * from the primary <code>RecordSpec</code> are used. See the {@link RecordSpec} documentation for details. * @param pFieldNames <code>String[]</code> of field names */ public void setFieldNames( String[] pFieldNames ); /** Indicate the start of the saving process. * <p>This method is called just before saving to the XML target document begins. * You can initialise any database connections or other resources that you need to use to process the data.</p> */ public void startProcess(); /** Indicate that another data record is available to save. * <p>Each data record is converted into XML by first calling this method to check that * another data record is available, and then calling {@link #nextRecord} to get the actual data. * Once this method returns <code>false</code>, processing finishes.</p> */ public boolean hasNextRecord(); /** Provide each data record as a <code>String[]</code> array for the XML target document. * <p>This is the most important method of the <code>RecordProvider</code> interface. This is where you * actually provide your data to <i>XML Manager</i>. The data is provided as a <code>String[]</code> array of field values. * You should always return a <code>String[]</code> array that is equal in length to the number of field paths * specified in the {@link RecordSpec}. Any <code>null</code> fields are set to empty strings, * and any missing fields are also set to empty strings. Any additional elements are ignored.</p> */ public String[] nextRecord(); /** Indicate the end of the saving process. * <p>This method is called once the XML source document has been fully output. You can use it to * release any resources such as database connections that you were using to create the data.</p> * <p>Note: this method <i>will</i> be called even if other errors occur, * so long as the call to {@link #startProcess} returned normally. * If your <code>startProcess</code> method does critical things, make sure that it fails cleanly.</p> */ public void endProcess(); }