import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.io.*;

/**
 * Simple class to read lines in from a text file. To use, create a
 * <code>LineReader</code> object, then send it the <code>readLine()</code>
 * message as many times as desired. When <code>readLine()</code> returns
 * the value <code>null</code>, the last line has been read, and the file
 * is automatically closed for you.
 * 
 * @author David Matuszek
 * @version 3.0
 */
public class LineReader {
    BufferedReader bufferedReader;
    
    /**
     * Constructor--called only after the file has been found.
     * 
     * @param bufferedReader The reader used internally by this LineReader.
     */
    private LineReader(BufferedReader bufferedReader) {
        this.bufferedReader = bufferedReader;
    }
    
    /**
     * Opens a dialog box that asks the user to choose a file to be read,
     * and returns a LineReader for the chosen file. If the user cancels
     * the dialog, or if the file cannot be read, this method returns
     * <code>null</code>.
     * 
     * @param message The message displayed at the top of the dialog box.
     * @return A LineReader object.
     */
    public static LineReader createReader(String message) {
        // use a JFileChooser dialog to get the name and directory of a file
        JFileChooser chooser = new JFileChooser();
        chooser.setDialogTitle(message);
        int result = chooser.showOpenDialog(null);
        if (result == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            try {
                if (file != null) {
                    String fileName = file.getCanonicalPath();
                    BufferedReader bufferedReader =
                        new BufferedReader(new FileReader(fileName));
                    return new LineReader(bufferedReader);
                }
            }
            catch (IOException e) {
                System.out.println("Unable to read selected file");
            }
        }
        return null;
    }
    
    /**
     * Opens a dialog box with a default message asking the user to choose
     * a file to be read, and returns a LineReader for the chosen file. If
     * the user cancels the dialog, or if the file cannot be read,
     * this method returns <code>null</code>.
     * 
     * @return A LineReader object.
     */
    public static LineReader createReader() {
        return createReader("Read lines from what file?");
    }
    
    /**
     * Once you have created a LineReader for a file, each call to
     * <code>readLine()</code> will return another line from that file.
     * After the last line in read, <code>readLine()</code> will return
     * <code>null</code> instead of a String, and will automatically
     * close the file.
     */
    public String readLine () {
        if (bufferedReader == null) {
            System.err.println("readLine() called without a valid input file.");
            return null;
        }
        try {
            String line = bufferedReader.readLine();
            if (line == null) close();
            return line;
        }
        catch (IOException e) {
            e.printStackTrace ();
        }
        return null;
    } 

    /**
     * Closes the file used by this LineReader. It is harmless to call this
     * method if the file has already been closed.
     */
    public void close() {
        if (bufferedReader != null) {
            try {
                bufferedReader.close();
            }
            catch (IOException e) {}
        }
    }
    
    /**
     * Main method used exclusively for testing.
     */
    public static void main(String[] args) {
        LineReader reader = LineReader.createReader();
        String line = reader.readLine();
        while (line != null) {
            System.out.println(line);
            line = reader.readLine();
        }
    }
}

