/* 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.*; /** Description of a badly formatted data line. * <p>This class describes a badly formatted data line. By default, * CSV processing stops when a bad line is encountered and a {@link CsvManagerException} * ({@link CsvManagerException#CODE_bad_line CODE_bad_line}) is thrown. The * {@link CsvManagerException#getBadLine CsvManagerException.getBadLine} method * returns a <code>BadLine</code> object describing the problem.</p> * <p>When {@link CsvManager#setRunInBackground CsvManager.setRunInbackground} is <code>true</code>, * the bad lines are collected and can be obtained using the * {@link CsvManager#getBadLines CsvManager.getBadLines} method.</p> * <p>Each bad line has the following attributes:</p> * <ul><li>{@link #getOriginalLine getOriginalLine}: the text of the original data line</li> * <li>{@link #getLineNumber getLineNumber}: the line number of the bad data line (counting starts from 1)</li> * <li>{@link #getErrorMsg getErrorMsg}: a technical message describing the problem</li> * <li>{@link #getErrorType getErrorType}: the type of error that occurred; incorrect CSV format ({@link #SYNTAX}), or invalid data ({@link #SEMANTIC})</li> * <li>{@link #getException getException}: the exception that caused the bad line, if any. MAY BE NULL.</li></ul> * <p>Sometimes the original data line is not available and the previous line or an empty <code>String</code> is provided. * For example, for an error at the start of loading, no lines have been read yet, but a single <code>BadLine</code> object * is still generated for consistency of error handling.</p> * <p>If you implement {@link LineListener}, parsing errors in the CSV data are reported * via {@link LineListener#handleBadLine LineListener.handleBadLine}. * You can also return your own <code>BadLine</code> * objects from {@link LineListener#handleLine LineListener.handleLine} if you encounter a semantic data error. * <code>BadLine</code> objects are also created when {@link LineProvider} instances throw an <code>Exception</code>. * This maintains the accuracy of the {@link CsvManager} statistics.</p> * <p>You may subclass <code>BadLine</code> in order to add your own * additional error description information.</p> * <p>The <b><a href="BadLine.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 LineProvider */ public class BadLine { /** Indicate that the data line was semantically invalid and that the value of one or more data fields is incorrect. */ public static final int SEMANTIC = 1; /** Indicate that the data line was syntactically invalid and could not be parsed correctly as a CSV format line. */ public static final int SYNTAX = 2; // protected instance /** The original text of the data line. */ protected String iOriginalLine = Standard.EMPTY; /** A technical error message describing the problem with the original data line. */ protected String iErrorMsg = Standard.EMPTY; /** The type of error, {@link #SYNTAX syntactic} or {@link #SEMANTIC semantic}. */ protected int iErrorType = SEMANTIC; /** The line number of the bad data line, counting from 1. */ protected long iLineNumber = 0; /** The <code>Exception</code> that caused the bad line, if any. */ protected Exception iException; /** Create a {@link #SEMANTIC} error description of a bad data line. * <p>The {@link LineListener#handleLine LineListener.handleLine} method can return a * <code>BadLine</code> object if the data line is semantically invalid. Use this constructor * to create the <code>BadLine</code> object to return. If there is no error, you should * return <code>null</code> from the <code>handleLine</code> method.</p> * @param pLineNumber line number if the bad data line, available from {@link LineListener#handleLine handleLine} parameters. * @param pOriginalLine original text of the line in the CSV file, available from {@link LineListener#handleLine handleLine} parameters. * @param pErrorMsg your own description of the problem * * @see #BadLine(long, String, String, int) * @see #BadLine(long, String, String, Exception) * @see #BadLine(long, String, String, int, Exception) */ public BadLine( long pLineNumber, String pOriginalLine, String pErrorMsg ) { this( pLineNumber, pOriginalLine, pErrorMsg, SEMANTIC, null ); } /** Create an error description of type <code>pErrorType</code> ({@link #SYNTAX} or {@link #SEMANTIC}). * <p>This constructor is used by {@link CsvManager} to create syntax error reports.</p> * @param pLineNumber line number if the bad data line, available from {@link LineListener#handleLine handleLine} parameters. * @param pOriginalLine original text of the line in the CSV file, available from {@link LineListener#handleLine handleLine} parameters. * @param pErrorMsg your own description of the problem * @param pErrorType one of {@link #SYNTAX} or {@link #SEMANTIC} * * @see #BadLine(long, String, String) * @see #BadLine(long, String, String, Exception) * @see #BadLine(long, String, String, int, Exception) */ public BadLine( long pLineNumber, String pOriginalLine, String pErrorMsg, int pErrorType ) { this( pLineNumber, pOriginalLine, pErrorMsg, pErrorType, null ); } /** Create an {@link #SEMANTIC} error description caused by a particular <code>Exception</code>. * @param pLineNumber line number if the bad data line, available from {@link LineListener#handleLine handleLine} parameters. * @param pOriginalLine original text of the line in the CSV file, available from {@link LineListener#handleLine handleLine} parameters. * @param pErrorMsg your own description of the problem * @param pException <code>Exception</code> that caused the bad line, optional * * @see #BadLine(long, String, String) * @see #BadLine(long, String, String, int) * @see #BadLine(long, String, String, int, Exception) */ public BadLine( long pLineNumber, String pOriginalLine, String pErrorMsg, Exception pException ) { this( pLineNumber, pOriginalLine, pErrorMsg, SEMANTIC, pException ); } /** Create an error description of a bad data line. * @param pLineNumber line number if the bad data line, available from {@link LineListener#handleLine handleLine} parameters. * @param pOriginalLine original text of the line in the CSV file, available from {@link LineListener#handleLine handleLine} parameters. * @param pErrorMsg your own description of the problem * @param pErrorType one of {@link #SYNTAX} or {@link #SEMANTIC} * @param pException <code>Exception</code> that caused the bad line, optional * * @see #BadLine(long, String, String) * @see #BadLine(long, String, String, int) * @see #BadLine(long, String, String, Exception) */ public BadLine( long pLineNumber, String pOriginalLine, String pErrorMsg, int pErrorType, Exception pException ) { if( SEMANTIC == pErrorType ) { iErrorType = SEMANTIC; } else if( SYNTAX == pErrorType ) { iErrorType = SYNTAX; } else { iErrorType = SEMANTIC; } if( null == pOriginalLine ) { iOriginalLine = Standard.EMPTY; } else { iOriginalLine = pOriginalLine; } if( null == pErrorMsg ) { iErrorMsg = Standard.EMPTY; } else { iErrorMsg = pErrorMsg; } if( pLineNumber < 1 ) { iLineNumber = 0; } else { iLineNumber = pLineNumber; } // optional, may be null iException = pException; } /** Get the line number of the bad data line. * <p>Line numbers always start at 1. If no line information is available, * this method returns 0.</p> */ public long getLineNumber() { return iLineNumber; } /** Get the text of the bad data line. * <p>If no line information is available, * this method returns an empty string.</p> */ public String getOriginalLine() { return iOriginalLine; } /** Get the error message describing the bad data line. * <p>This message is normally of a technical nature.</p> */ public String getErrorMsg() { return iErrorMsg; } /** Get the type of error that occurred. * <p>The current error types are {@link #SEMANTIC}, for * invalid data values, and {@link #SYNTAX}, for CSV data that * cannot be parsed due to formatting errors.</p> */ public int getErrorType() { return iErrorType; } /** Get the <code>Exception</code> that caused the bad line. * <p><b>WARNING: MAY BE NULL.</b> <i>There may not be a causing exception.</i></p> */ public Exception getException() { return iException; } /** A utility method useful for debugging. * <p>returns a <code>String</code> in the format:<pre> * [CSV:BadLine:1:error message text:SYNTAX|SEMANTIC:original data line text:exception msg] * </pre> */ public String toString() { return "[CSV:BadLine:"+iLineNumber+":"+iErrorMsg+":" +(SEMANTIC==iErrorType?"SEMANTIC":(SYNTAX==iErrorType?"SYNTAX":""+iErrorType)) +":"+iOriginalLine +(null==iException?"":":"+iException.getMessage())+"]"; } /** Append more text to the error message. * @param pAppend text to append */ protected void appendErrorMsg( String pAppend ) { iErrorMsg += (null == pAppend)? "" : pAppend ; } }