Open Source Repository

Home /supercsv/super-csv-2.2.0 | Repository Home



org/supercsv/io/AbstractCsvReader.java
/*
 * Copyright 2007 Kasper B. Graversen
 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 
 *     http://www.apache.org/licenses/LICENSE-2.0
 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.supercsv.io;

import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.exception.SuperCsvConstraintViolationException;
import org.supercsv.exception.SuperCsvException;
import org.supercsv.prefs.CsvPreference;
import org.supercsv.util.Util;

/**
 * Defines the standard behaviour of a CSV reader.
 
 @author Kasper B. Graversen
 @author James Bassett
 */
public abstract class AbstractCsvReader implements ICsvReader {
  
  private final ITokenizer tokenizer;
  
  private final CsvPreference preferences;
  
  // the current tokenized columns
  private final List<String> columns = new ArrayList<String>();
  
  // the number of CSV records read
  private int rowNumber = 0;
  
  /**
   * Constructs a new <tt>AbstractCsvReader</tt>, using the default {@link Tokenizer}.
   
   @param reader
   *            the reader
   @param preferences
   *            the CSV preferences
   @throws NullPointerException
   *             if reader or preferences are null
   */
  public AbstractCsvReader(final Reader reader, final CsvPreference preferences) {
    ifreader == null ) {
      throw new NullPointerException("reader should not be null");
    else ifpreferences == null ) {
      throw new NullPointerException("preferences should not be null");
    }
    
    this.preferences = preferences;
    this.tokenizer = new Tokenizer(reader, preferences);
  }
  
  /**
   * Constructs a new <tt>AbstractCsvReader</tt>, using a custom {@link Tokenizer} (which should have already been set
   * up with the Reader, CsvPreference, and CsvContext). This constructor should only be used if the default Tokenizer
   * doesn't provide the required functionality.
   
   @param tokenizer
   *            the tokenizer
   @param preferences
   *            the CSV preferences
   @throws NullPointerException
   *             if tokenizer or preferences are null
   */
  public AbstractCsvReader(final ITokenizer tokenizer, final CsvPreference preferences) {
    iftokenizer == null ) {
      throw new NullPointerException("tokenizer should not be null");
    else ifpreferences == null ) {
      throw new NullPointerException("preferences should not be null");
    }
    
    this.preferences = preferences;
    this.tokenizer = tokenizer;
  }
  
  /**
   * Closes the Tokenizer and its associated Reader.
   */
  public void close() throws IOException {
    tokenizer.close();
  }
  
  /**
   * {@inheritDoc}
   */
  public String get(final int n) {
    return columns.get(n - 1)// column numbers start at 1
  }
  
  /**
   * {@inheritDoc}
   */
  public String[] getHeader(final boolean firstLineCheckthrows IOException {
    
    iffirstLineCheck && tokenizer.getLineNumber() != ) {
      throw new SuperCsvException(String.format(
        "CSV header must be fetched as the first read operation, but %d lines have already been read",
        tokenizer.getLineNumber()));
    }
    
    ifreadRow() ) {
      return columns.toArray(new String[columns.size()]);
    }
    
    return null;
  }
  
  /**
   * {@inheritDoc}
   */
  public int getLineNumber() {
    return tokenizer.getLineNumber();
  }
  
  /**
   * {@inheritDoc}
   */
  public String getUntokenizedRow() {
    return tokenizer.getUntokenizedRow();
  }
  
  /**
   * {@inheritDoc}
   */
  public int getRowNumber() {
    return rowNumber;
  }
  
  /**
   * {@inheritDoc}
   */
  public int length() {
    return columns.size();
  }
  
  /**
   * Gets the tokenized columns.
   
   @return the tokenized columns
   */
  protected List<String> getColumns() {
    return columns;
  }
  
  /**
   * Gets the preferences.
   
   @return the preferences
   */
  protected CsvPreference getPreferences() {
    return preferences;
  }
  
  /**
   * Calls the tokenizer to read a CSV row. The columns can then be retrieved using {@link #getColumns()}.
   
   @return true if something was read, and false if EOF
   @throws IOException
   *             when an IOException occurs
   @throws SuperCsvException
   *             on errors in parsing the input
   */
  protected boolean readRow() throws IOException {
    iftokenizer.readColumns(columns) ) {
      rowNumber++;
      return true;
    }
    return false;
  }
  
  /**
   * Executes the supplied cell processors on the last row of CSV that was read and populates the supplied List of
   * processed columns.
   
   @param processedColumns
   *            the List to populate with processed columns
   @param processors
   *            the cell processors
   @return the updated List
   @throws NullPointerException
   *             if processedColumns or processors is null
   @throws SuperCsvConstraintViolationException
   *             if a CellProcessor constraint failed
   @throws SuperCsvException
   *             if the wrong number of processors are supplied, or CellProcessor execution failed
   */
  protected List<Object> executeProcessors(final List<Object> processedColumns, final CellProcessor[] processors) {
    Util.executeCellProcessors(processedColumns, getColumns(), processors, getLineNumber(), getRowNumber());
    return processedColumns;
  }
  
}