/**
   * Gets the next row from the current data access object data source. <i>Side effect:</i> Updates
   * the current record number
   */
  @Override
  public Row readRow() throws DataAccessObjectException {
    if (!isOpen) {
      open();
    }

    List<String> record;
    synchronized (lock) {
      try {
        record = csvReader.nextRecord();
      } catch (IOException e) {
        throw new DataAccessObjectException(e);
      }
    }

    if (!DAORowUtil.isValidRow(record)) {
      return null;
    }

    if (record.size() > headerRow.size()) {
      String errMsg =
          Messages.getFormattedString(
              "CSVFileDAO.errorRowTooLarge",
              new String[] {
                String.valueOf(currentRowNumber),
                String.valueOf(record.size()),
                String.valueOf(headerRow.size())
              });
      throw new DataAccessRowException(errMsg);
    }

    Row row = new Row(record.size());

    for (int i = 0; i < headerRow.size(); i++) {
      String value = record.get(i);
      if (value == null) {
        value = "";
      }
      row.put(headerRow.get(i), value);
    }
    currentRowNumber++;
    return row;
  }
 private void readHeaderRow() throws DataAccessObjectInitializationException {
   try {
     synchronized (lock) {
       headerRow = csvReader.nextRecord();
     }
     if (headerRow == null) {
       LOGGER.error(Messages.getString("CSVFileDAO.errorHeaderRow"));
       throw new DataAccessObjectInitializationException(
           Messages.getString("CSVFileDAO.errorHeaderRow"));
     }
   } catch (IOException e) {
     String errMsg = Messages.getString("CSVFileDAO.errorHeaderRow");
     LOGGER.error(errMsg, e);
     throw new DataAccessObjectInitializationException(errMsg, e);
   } finally {
     // if there's a problem getting header row, the stream needs to be closed
     if (headerRow == null) {
       IOUtils.closeQuietly(input);
     }
   }
 }