gt:                     table = new Table(tableName, columns);
context: /*
  // This software is subject to the terms of the Eclipse Public License v1.0
  // Agreement, available at the following URL:
  // http://www.eclipse.org/legal/epl-v10.html.
  // You must accept the terms of that agreement to use this software.
  //
  // Copyright (C) 2004-2005 Julian Hyde
  // Copyright (C) 2005-2011 Pentaho
  // All Rights Reserved.
  */
  
  package mondrian.test.loader;
  
  import java.io.*;
  import java.util.*;
  import java.util.regex.Pattern;
  
  /**
   * Implementation of {@link DBLoader} which gets its Tables by reading CSV files
   * using the {@link CsvLoader} class and is the loader use for CSV junit tests.
   *
   * <p>
   * <code>CsvDBLoader</code> requires that the CSV files have a specific format
   * as defined:
   *
   * <blockquote><pre>
   * list_of_csv_files : (csv_file)+
   * csv_file: table_definitions
   * table_definitions: (table_definition)+
   * table_definition: actions table_name column_names column_types
   *          (file_name or nos_of_rows or rows)
   * actions: (action)*
   * action: '##' (ActionBefore: | ActionAfter:) action_type
   * action_type: DropIndex index_name | CreateIndex index_name column_name
   * table_name: '##' TableName: table_name
   * column_names: '##' ColumnNames: column_name (',' column_name)*
   * column_types: '##' ColumnTypes: column_types ('.' column_types)*
   * file_name:'##' FileName: relative_filename ?
   * nos_of_rows:'##' NosOfRows: number
   * column_types: type (':' null)
   * type: "INTEGER" "DECIMAL(*,*)" "SMALLINT"
   *       "VARCHAR(*)" "REAL" "BOOLEAN"
   *       "BIGINT" "DATE" "TIMESTAMP"
   *  rows: (row)*
   *  row: value (',' value)*
   *
   *  if FileName is given, then
   *      there is no NosOfRows
   *      the file can only contains rows
   *  else if NosOfRows is given, then
   *      there is no FileName
   *      the number of rows in current file are rows for table
   *  else
   *      the all remaining rows in current file are rows for table
   *  fi
   *
   *  comment lines start with '#'
   *
   * </pre></blockquote>
   * <p>
   * See the testsrc/main/mondrian/rolap/aggmatcher/BUG_1541077.csv file
   * for an example.
   *
   *
   * @author Richard M. Emberson
   */
  public class CsvDBLoader extends DBLoader {
  
  
      public static final String ACTION_BEFORE_TAG = "ActionBefore:";
      public static final String ACTION_AFTER_TAG = "ActionAfter:";
      public static final String DROP_INDEX_TAG = "DropIndex";
      public static final String CREATE_INDEX_TAG = "CreateIndex";
  
      public static final String TABLE_NAME_TAG = "TableName:";
      public static final String COLUMN_NAMES_TAG = "ColumnNames:";
      public static final String COLUMN_TYPES_TAG = "ColumnTypes:";
      public static final String FILE_NAME_TAG = "FileName:";
      public static final String NOS_OF_ROWS_TAG = "NosOfRows:";
  
      private File inputDirectory;
      private String inputDirectoryRegex;
      private File[] inputFiles;
      private File inputFile;
  
      public CsvDBLoader() {
          super();
      }
  
      public void setInputDirectory(File inputDirectory) {
          this.inputDirectory = inputDirectory;
      }
  
      public File getInputDirectory() {
          return this.inputDirectory;
      }
  
      public void setInputDirectoryRegex(String inputDirectoryRegex) {
          this.inputDirectoryRegex = inputDirectoryRegex;
      }
  
      public String getInputDirectoryRegex() {
          return this.inputDirectoryRegex;
      }
  
      public void setInputFiles(File[] inputFiles) {
          this.inputFiles = inputFiles;
      }
  
      public File[] getInputFiles() {
          return this.inputFiles;
      }
  
      public void setInputFile(File inputFile) {
          this.inputFile = inputFile;
      }
  
      public File getInputFile() {
          return this.inputFile;
      }
  
      public Table[] getTables() throws Exception {
          initialize();
  
          if (this.inputDirectory != null) {
              return getTablesFromDirectory();
          } else if (this.inputFiles != null) {
              return getTablesFromFiles();
          } else if (this.inputFile != null) {
              return getTablesFromFile();
          } else {
              return new Table[0];
          }
      }
  
      public Table[] getTablesFromDirectory() throws Exception {
          File[] files;
          if (this.inputDirectoryRegex == null) {
              files = this.inputDirectory.listFiles();
          } else {
              final Pattern pat = Pattern.compile(this.inputDirectoryRegex);
              files = this.inputDirectory.listFiles(
                  new FilenameFilter() {
                      public boolean accept(File dir, String name) {
                          return pat.matcher(name).matches();
                      }
                  }
              );
              if (files == null) {
                  files = new File[0];
              }
          }
          return getTables(files);
      }
  
      public Table[] getTablesFromFiles() throws Exception {
          return getTables(this.inputFiles);
      }
  
      public Table[] getTablesFromFile() throws Exception {
          List<Table> list = new ArrayList<Table>();
          loadTables(this.inputFile, list);
          return list.toArray(new Table[list.size()]);
      }
  
      public Table[] getTables(File[] files) throws Exception {
          List<Table> list = new ArrayList<Table>();
          for (File file : files) {
              loadTables(file, list);
          }
          return list.toArray(new Table[list.size()]);
      }
  
      public Table[] getTables(Reader reader) throws Exception {
          List<Table> list = new ArrayList<Table>();
          loadTables(reader, list);
          return list.toArray(new Table[list.size()]);
      }
  
      public static class ListRowStream implements RowStream {
          private List<Row> list;
          ListRowStream() {
              this(new ArrayList<Row>());
          }
          ListRowStream(List<Row> list) {
              this.list = list;
          }
          void add(Row row) {
              this.list.add(row);
          }
          public Iterator<Row> iterator() {
              return this.list.iterator();
          }
      }
  
      public static class CsvLoaderRowStream implements RowStream {
          private final CsvLoader csvloader;
          CsvLoaderRowStream(CsvLoader csvloader) {
              this.csvloader = csvloader;
          }
          public Iterator<Row> iterator() {
              return new Iterator<Row>() {
                  String[] line;
                  public boolean hasNext() {
                      try {
                          boolean hasNext =
                              CsvLoaderRowStream.this.csvloader.hasNextLine();
                          if (! hasNext) {
                              CsvLoaderRowStream.this.csvloader.close();
                          } else {
                              line = CsvLoaderRowStream.this.csvloader.nextLine();
                              // remove comment lines
                              if (line.length > 0
                                  && line[0].length() > 0
                                  && line[0].startsWith("#"))
                              {
                                  return hasNext();
                              }
                          }
                          return hasNext;
                      } catch (IOException ex) {
                          //
                      }
                      return false;
                  }
                  public Row next() {
                      return new RowDefault(line);
  /*
                      return new RowDefault(
                          CsvLoaderRowStream.this.csvloader.nextLine());
  */
                  }
                  public void remove() {
                  }
              };
          }
      }
  
      /**
       * Looks for a file relative to the current directory and all of its
       * parent directories. This gives a little flexibility if you invoke a
       * test in a sub-directory.
       *
       * @param file File
       * @return File within current directory or a parent directory.
       */
      private static File resolveFile(File file) {
          if (file.isAbsolute()) {
              return file;
          } else {
              File base = new File(System.getProperty("user.dir"));
              while (base != null) {
                  File file2 = new File(base, file.getPath());
                  if (file2.exists()) {
                      return file2;
                  }
                  base = base.getParentFile();
              }
          }
          return file;
      }
  
      public void loadTables(File file, List<Table> tableList) throws Exception {
          Reader reader = new FileReader(resolveFile(file));
          loadTables(reader, tableList);
      }
  
      public void loadTables(Reader reader, List<Table> tableList)
          throws Exception
      {
          CsvLoader csvloader = null;
          try {
              Table table = null;
              List<String> beforeActionList = new ArrayList<String>();
              List<String> afterActionList = new ArrayList<String>();
              String tableName = null;
              String[] columnNames = null;
              String[] columnTypes = null;
              String fileName = null;
              int nosOfRowsStr = -1;
              boolean ok = false;
              Column[] columns;
              csvloader = new CsvLoader(reader);
              int lineNos = 0;
              while (csvloader.hasNextLine()) {
                  String[] values = csvloader.nextLine();
                  lineNos++;
  //System.out.println("CsvLoader.loadTables: lineNos=" +lineNos);
                  if (values.length == 0) {
                      continue;
                  }
                  String value0 = values[0];
  //System.out.println("CsvLoader.loadTables: value0=" +value0);
                  if (value0.startsWith("##") && (fileName == null)) {
                      if (table != null) {
                          table = null;
                          beforeActionList.clear();
                          afterActionList.clear();
                          tableName = null;
                          columnNames = null;
                          columnTypes = null;
                          fileName = null;
                          nosOfRowsStr = -1;
                      }
                      // meta info
                      int index = value0.indexOf(ACTION_BEFORE_TAG);
                      if (index != -1) {
                          String s = value0.substring(
                              index + ACTION_BEFORE_TAG.length());
                          if (s.length() == 0) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no action before sql"
                                  + ", linenos " + lineNos);
                          }
                          s = s.trim();
                          if (! s.startsWith(DROP_INDEX_TAG)) {
                              // only support dropping indexes currently
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " unknown before action" + s
                                  + ", linenos " + lineNos);
                          }
                          // get index name
                          index = s.indexOf(' ');
                          if (index < 0) {
                              // only support dropping indexes currently
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no index name in before action" + s
                                  + ", linenos " + lineNos);
                          }
                          s = s.substring(index + 1);
                          s = s.trim();
                          beforeActionList.add(s);
                          continue;
                      }
  
                      index = value0.indexOf(ACTION_AFTER_TAG);
                      if (index != -1) {
                          String s = value0.substring(
                              index + ACTION_AFTER_TAG.length());
                          if (s.length() == 0) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no action after sql"
                                  + ", linenos " + lineNos);
                          }
                          s = s.trim();
                          if (! s.startsWith(CREATE_INDEX_TAG)) {
                              // only support creating indexes currently
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " unknown before action" + s
                                  + ", linenos " + lineNos);
                          }
                          // get index name
                          index = s.indexOf(' ');
                          if (index < 0) {
                              // only support creating indexes currently
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no index_name/column_name in after action"
                                  + s + ", linenos " + lineNos);
                          }
                          // CreateIndex index_name column_name
                          s = s.substring(index + 1);
                          s = s.trim();
                          index = s.indexOf(' ');
                          // just check that there is a space and
                          if (index < 0) {
                              // only support creating indexes currently
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no column_name after index_name "
                                  + "in after action" + s
                                  + ", linenos " + lineNos);
                          }
                          afterActionList.add(s);
                          continue;
                      }
  
                      index = value0.indexOf(TABLE_NAME_TAG);
                      if (index != -1) {
                          String s = value0.substring(
                              index + TABLE_NAME_TAG.length());
                          if (s.length() == 0) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no table name"
                                  + ", linenos " + lineNos);
                          }
                          s = s.trim();
                          if (tableName != null) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " new table name \"" + s
                                  + "\" while processing table name \""
                                  + tableName
                                  + "\", linenos " + lineNos);
                          }
                          tableName = s;
                          continue;
                      }
                      index = value0.indexOf(COLUMN_NAMES_TAG);
                      if (index != -1) {
                          String s = value0.substring(
                              index + COLUMN_NAMES_TAG.length());
                          if (s.length() == 0) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no column names"
                                  + ", linenos " + lineNos);
                          }
                          if (tableName == null) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no table name for columns "
                                  + ", linenos " + lineNos);
                          }
                          values[0] = s.trim();
                          columnNames = values;
                          continue;
                      }
                      index = value0.indexOf(COLUMN_TYPES_TAG);
                      if (index != -1) {
                          String s = value0.substring(
                              index + COLUMN_TYPES_TAG.length());
                          if (s.length() == 0) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no column types"
                                  + ", linenos " + lineNos);
                          }
                          if (columnNames == null) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no column names for columns types"
                                  + ", linenos " + lineNos);
                          }
                          values[0] = s.trim();
                          columnTypes = values;
  
                          if (columnNames.length != columnTypes.length) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " number of column names \""
                                  + columnNames.length
                                  + "\" does not equal "
                                  + " number of column types \""
                                  + columnTypes.length
                                  + "\", linenos " + lineNos);
                          }
                          continue;
                      }
  
                      ok = true;
  
                      index = value0.indexOf(FILE_NAME_TAG);
                      if (index != -1) {
                          String s = value0.substring(
                              index + FILE_NAME_TAG.length());
                          if (s.length() == 0) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no file name "
                                  + ", linenos " + lineNos);
                          }
                          if (columnTypes == null) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no column types for file name"
                                  + ", linenos " + lineNos);
                          }
                          fileName = s.trim();
                          continue;
                      }
                      index = value0.indexOf(NOS_OF_ROWS_TAG);
                      if (index != -1) {
                          String s = value0.substring(
                              index + NOS_OF_ROWS_TAG.length());
                          if (s.length() == 0) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no number of rows"
                                  + ", linenos " + lineNos);
                          }
                          if (columnTypes == null) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no column types for file name"
                                  + ", linenos " + lineNos);
                          }
                          nosOfRowsStr = Integer.parseInt(s.trim());
                          continue;
                      }
                  } else if (value0.startsWith("# ")) {
                      // comment, do nothing
                  } else {
  //System.out.println("CsvLoader.loadTables: ELSE");
                      // rows
                      if (! ok) {
                          if (tableName == null) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no table name before rows"
                                  + ", linenos " + lineNos);
                          }
                          if (columnNames == null) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no column names before rows"
                                  + ", linenos " + lineNos);
                          }
                          if (columnTypes == null) {
                              throw new IOException(
                                  "CSV File parse Error: "
                                  + " no column types before rows"
                                  + ", linenos " + lineNos);
                          }
                      }
                      columns = loadColumns(columnNames, columnTypes, lineNos);
  