
import java.net.*;
import java.io.*;
import java.util.*;

//--------------------------------------------
/**
 * This class is a plain text data file which is in a simple format
 * which contains information about language sound files.
 * As the file is parsed it will construct Record objects.
 * Parsing may use a BreakIterator class or a StreamTokenizer
 * to break the  
 * @author= bumble.sf.net
 */
public class DataFile extends Object
{
  //--------------------------------------------
  /** The location of the data file on the internet */
  // private Url location;
  //--------------------------------------------
  /** Some collection structure of the data Records */
  private Vector records;
  //--------------------------------------------
  private boolean isGood;
  //--------------------------------------------
  private StringBuffer error;
  //--------------------------------------------
  private StringBuffer errorMessages;
  //--------------------------------------------
  private Date startTime;
  //--------------------------------------------
  private Date finishTime;
  //--------------------------------------------
  private int linesRead;
  //--------------------------------------------
  /** A character on a line by itself which separates each record of 
   *  the datafile */
  public static String RECORD_SEPARATOR = "=";
  //--------------------------------------------
  private static String NEWLINE = System.getProperty("line.separator");



  //--------------------------------------------
  /** creates a DataFile object with no data.  */
  public DataFile()
  {
    this.isGood = true;
    this.error = new StringBuffer("");
    this.errorMessages = new StringBuffer("");
    this.records = new Vector();
    this.linesRead = 0;
  } 

  //--------------------------------------------
  /** creates the object from a reader */
  public DataFile(Reader rTextData) throws Exception
  {
    this();
    this.loadData(rTextData);
  } //-- constr: (InputStream)

  //--------------------------------------------
  /** attempts to load data from the given file */
  public DataFile(String sFileName) throws Exception
  {
    this();
    File fDataFile = new File(sFileName);

    if (!fDataFile.exists())
    {
      return;
    }

    FileReader frTextData = new FileReader(fDataFile);
    this.loadData(frTextData);

  } //-- constr: (InputStream)


  //--------------------------------------------
  /** adds a record to the set */
  public void addRecord(Record rNewRecord)
  {
    this.records.addElement(rNewRecord);
  }

  //--------------------------------------------
  /** creates a DataFile object from a buffered reader */
  public void loadData(Reader rTextData)
  {
    this.startTime = new Date();
    BufferedReader brReader = new BufferedReader(rTextData);

    StringBuffer sbRecordText = new StringBuffer("");    
    Record rCurrentRecord;
    String sCurrentLine;

    sCurrentLine = " ";

    while (sCurrentLine != null)
    {
      //System.out.println("parsing line [" + sbCurrentLine + "]");
      if (sCurrentLine.equalsIgnoreCase(this.RECORD_SEPARATOR))
      {
        rCurrentRecord = new Record(sbRecordText.toString());
        this.addRecord(rCurrentRecord);
        sbRecordText.setLength(0);
      }
      else
      {
        sbRecordText.append(sCurrentLine);
        sbRecordText.append(NEWLINE);
      }

      try
      {
        sCurrentLine = brReader.readLine().trim();
      }
      catch (IOException e)
      {
        this.isGood = false;
        this.error.append("Problem reading inputstream ");
        this.error.append("at line: " + this.linesRead);
        this.errorMessages.append(e);
        this.finishTime = new Date();
        return;
      }
      catch (NullPointerException ee)
      {
        sCurrentLine = null;
      } //-- try

      this.linesRead++;
    } //-- while more lines

    this.finishTime = new Date();
  } //-- 

  //--------------------------------------------
  /**
   * Return those Records which represent single word sound
   * files and their word data
   */
  public Vector getWordsOnly()
  { 
    Vector hhReturn = new Vector();
    Record rCurrentRecord;
    Enumeration ii = this.records.elements();
    while (ii.hasMoreElements()) 
    {
      rCurrentRecord = (Record)ii.nextElement();
      if (rCurrentRecord.isSingleWord())
       { hhReturn.addElement(rCurrentRecord); } 
    } //-- while
      
    return hhReturn;
  }
  
  //--------------------------------------------
  /** return only records with a sound resource */
  public Vector getSoundRecords()
  {
    Vector hhReturn = new Vector();
    Record rCurrentRecord;
    Enumeration ii = this.records.elements();
    while (ii.hasMoreElements()) 
    {
      rCurrentRecord = (Record)ii.nextElement();
      if (rCurrentRecord.hasSound())
       { hhReturn.addElement(rCurrentRecord); } 
    } //-- while
      
    return hhReturn;
  }

  //--------------------------------------------
  /** return all records */
  public Vector getRecords()
  {
    return this.records;
  }


  //--------------------------------------------
  /** the amount of time it takes to load the data */
  public long getLoadDuration()
  {
    if (this.finishTime == null) { return 0; }
    if (this.startTime == null) { return 0; }
    return this.finishTime.getTime() - this.startTime.getTime();
  }


  //--------------------------------------------
  /** count the total number of records */
  public int countRecords()
   { return this.records.size(); }


  //--------------------------------------------
  /** prints some information about the object */
  public String printReport()
  { 
    StringBuffer sbOutput = new StringBuffer();
    sbOutput.append("Load Time :" + this.getLoadDuration());
    sbOutput.append(NEWLINE);
    sbOutput.append("Lines read:");
    sbOutput.append(this.linesRead);
    sbOutput.append(NEWLINE);

    sbOutput.append("Number of Records:" + this.countRecords());
    sbOutput.append(NEWLINE);
    sbOutput.append("Data is ok:" + this.isGood);
    sbOutput.append(NEWLINE);

    if (!this.error.equals(""))
    {
      sbOutput.append("Error cause:" + this.error);
      sbOutput.append(NEWLINE);
    }

    sbOutput.append("Error messages:" + this.errorMessages);
    sbOutput.append(NEWLINE);
      
    return sbOutput.toString();
  } //-- method: printReport

  //--------------------------------------------
  /** creates some kind of textual representation of this datafile
   *  class. Probably suitable for displaying the contents of the 
   *  datafile on a console */
  public String print()
  { 
    StringBuffer sbOutput = new StringBuffer();
    Record rCurrentRecord;
    Enumeration ii = this.records.elements();
    while (ii.hasMoreElements()) 
    {
      rCurrentRecord = (Record)ii.nextElement();
      sbOutput.append(rCurrentRecord.print());
    } //-- while
      
    return sbOutput.toString();
  } //-- method: print
  

  //--------------------------------------------
  /** creates some kind of textual representation of this datafile
   *  class. */
  public String toString()
  { 
    StringBuffer sbOutput = new StringBuffer();
    Record rCurrentRecord;
    Enumeration ii = this.records.elements();
    while (ii.hasMoreElements()) 
    {
      rCurrentRecord = (Record)ii.nextElement();
      sbOutput.append(rCurrentRecord.toString());
    } //-- while
      
    return sbOutput.toString();
  } 


  //--------------------------------------------
  /** A main method to allow the class to be tested on
   *  the console. */
  public static void main(String[] args) throws Exception
  {
    String sUsageMessage = "test usage: java DataFile [file]";
    StringBuffer sbOutput = new StringBuffer("");


    if (args.length == 0)
    {	    
      System.out.println(sUsageMessage);
      System.exit(-1);
    }

    File fTest = new File(args[0]);
    System.out.println("Trying to create the input stream...");
    FileReader rTest = new FileReader(fTest);
    System.out.println("Trying to create the DataFile object...");
    DataFile dfTest = new DataFile(rTest);
    System.out.println("DataFile object created");
    //System.out.println(dfTest.toString());
    System.out.println(dfTest.printReport());



  } //-- main()
} //-- DataFile class
