/* 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; import com.ricebridge.xmlman.in.RecordTrigger; import org.jostraca.util.Internal; import org.jostraca.util.Standard; import java.util.*; /** Helper class for implementing the {@link RecordListener} interface. * <p>Use of this class will help ensure future compatibility with any XML Manager API changes. * Subclasses should implement the <code>*Impl</code> methods (for example, {@link #handleRecordImpl handleRecordImpl}) * rather than the declared interface methods such as {@link #handleRecord handleRecord}. * See the {@link RecordListener} interface documentation for a description of the calling sequence of the methods * in this class. </p> * <p>The <b><a href="RecordListenerSupport.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 abstract class RecordListenerSupport implements RecordListener { // protected instance /** Record specification field names, if specified in the {@link RecordSpec} object associated with this {@link RecordListener}. * <b>NOTE: may be empty.</b> */ protected String[] iFieldNames = new String[]{}; // public methods /** Helper implementation of {@link RecordListener#setXmlSpec RecordListener.setXmlSpec}. * Subclasses should implement {@link #setXmlSpecImpl setXmlSpecImpl}. */ public void setXmlSpec( XmlSpec pXmlSpec ) { XmlSpec xs = (XmlSpec) Internal.null_arg( pXmlSpec ); try { setXmlSpecImpl( xs ); } catch( XmlManagerException xme ) { throw xme; } catch( Exception e ) { throw new XmlManagerException( XmlManagerException.CODE_recordlistener_set, new String[] { "record-listener-class", this.getClass().getName(), "methodname", "setXmlSpecImpl", "setargument", String.valueOf(xs) }, e ); } } /** Helper implementation of {@link RecordListener#setFieldNames RecordListener.setFieldNames}. * Subclasses should implement {@link #setFieldNamesImpl setFieldNamesImpl}. */ public void setFieldNames( String[] pFieldNames ) { String[] fn = (String[]) Internal.null_array( pFieldNames ); try { setFieldNamesImpl( fn ); } catch( XmlManagerException xme ) { throw xme; } catch( Exception e ) { throw new XmlManagerException( XmlManagerException.CODE_recordlistener_set, new String[] { "record-listener-class", this.getClass().getName(), "methodname", "setFieldNamesImpl", "setargument", Arrays.asList(fn).toString() }, e ); } } /** Helper implementation of {@link RecordListener#startProcess RecordListener.startProcess}. * Subclasses should implement {@link #startProcessImpl startProcessImpl}. */ public void startProcess() { try { startProcessImpl(); } catch( XmlManagerException xme ) { throw xme; } catch( Exception e ) { throw new XmlManagerException( XmlManagerException.CODE_recordlistener_exception, new String[] { "record-listener-class", this.getClass().getName(), "methodname", "startProcessImpl" }, e ); } } /** Helper implementation of {@link RecordListener#handleRecord RecordListener.handleRecord}. * Subclasses should implement {@link #handleRecordImpl handleRecordImpl}. */ public BadRecord handleRecord( String[] pRecord, long pRecordNumber ) { String[] record = (String[]) Internal.null_arg( pRecord ); // check nulls for( int cI = 0; cI < record.length; cI++ ) { if( null == record[cI] ) { record[cI] = Standard.EMPTY; } } long recnum = pRecordNumber; if( recnum < 1 ) { recnum = 1; } // returns null if OK BadRecord badrec = null; try { badrec = handleRecordImpl( record, recnum ); } catch( XmlManagerException xme ) { throw xme; } catch( Exception e ) { throw new XmlManagerException( XmlManagerException.CODE_handlerecord_exception, new String[] { "record-listener-class", this.getClass().getName(), "record", String.valueOf( Arrays.asList(record) ), "recnum", String.valueOf(recnum) }, e ); } return badrec; } /** Helper implementation of {@link RecordListener#endProcess RecordListener.endProcess}. * Subclasses should implement {@link #endProcessImpl endProcessImpl}. */ public void endProcess() { try { endProcessImpl(); } catch( XmlManagerException xme ) { throw xme; } catch( Exception e ) { throw new XmlManagerException( XmlManagerException.CODE_recordlistener_exception, new String[] { "record-listener-class", this.getClass().getName(), "methodname", "endProcessImpl" }, e ); } } // protected methods /** Implement this method to receive the current {@link XmlSpec} settings. * <p>This method is optional for subclasses, as an empty implementation is provided here.</p> * @param pXmlSpec XML specification * @see #setXmlSpec * @see RecordListener#setXmlSpec */ protected void setXmlSpecImpl( XmlSpec pXmlSpec ) throws Exception { // empy implementation } /** Implement this method to obtain the record specification field names, if available. * <p>The default implementation stores the field names in the {@link #iFieldNames} member variable. * This method is optional for subclasses, as an implementation is provided here.</p> * @param pFieldNames data record field names * @see #setFieldNames * @see RecordListener#setFieldNames */ protected void setFieldNamesImpl( String[] pFieldNames ) throws Exception { iFieldNames = (String[]) Internal.null_array( pFieldNames ); } /** Implement this method to receive notification that the saving of XML data is about to start. * <p>This method is optional for subclasses, as an empty implementation is provided here.</p> * @see #startProcess * @see RecordListener#startProcess */ protected void startProcessImpl() throws Exception { // empty implementation } /** Implement this method to receive record data as it parsed. * <p>The record number is specific to each {@link RecordSpec}. * This method must be implemented by subclasses.</p> * @param pRecord record data as a <code>String[]</code> * @param pRecordNumber current count of records * @see #handleRecord * @see RecordListener#handleRecord */ protected abstract BadRecord handleRecordImpl( String[] pRecord, long pRecordNumber ) throws Exception; /** Implement this method to receive notification that the saving of XML data has ended. * <p>This method is optional for subclasses, as an empty implementation is provided here.</p> * @see #endProcess * @see RecordListener#endProcess */ protected void endProcessImpl() throws Exception { // empty implementation } }