/*
 This file is part of the software framework JStatCom, 
 a library for building applications for data based analysis.

 Copyright (C) 2000-2005  Markus Kraetzig

 This library is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as
 published by the Free Software Foundation; either version 2.1 of the
 License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 USA
 */

package com.jstatcom.io;

import java.awt.Component;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;

import org.apache.log4j.Logger;

import EDU.oswego.cs.dl.util.concurrent.misc.SwingWorker;

import com.jstatcom.model.JSCSArray;

/**
 * Support for convenient file selection. This class is a Singleton and can be
 * accessed by the getInstance method.
 * 
 * @author A. Benkwitz, Markus Kraetzig 
 */
public final class FileSupport {
    private static final Logger log = Logger.getLogger(FileSupport.class);

    private static final FileSupport fileSupport = new FileSupport();

    private JFileChooser fileChooserOpenDat = null;

    private JFileChooser fileChooserSave = null;

    private final ExtensionFileFilter projectFileFilter = new ExtensionFileFilter(
            "jsc", "Project Files");

    private final ExtensionFileFilter textFileFilter = new ExtensionFileFilter(
            "txt", "ASCII Text Files");

    private String saveTextDirectory = null;

    private String dataDirectory = null;

    private String projectFile = "";

    private String projectDirectory = null;

    private FileFilter currentSaveFilter = null;

    /**
     * Swing worker for background creation of JFileChooser,.
     */
    private static class WorkerFileChooser extends SwingWorker {

        private JFileChooser ret = null;

        public Object construct() {
            if (ret == null)
                ret = new JFileChooser();
            return ret;
        }

        public Object get() {
            return ret;
        }
    }

    private final WorkerFileChooser fileChooserOpenDat_Worker = new WorkerFileChooser();

    private final WorkerFileChooser fileChooserSave_Worker = new WorkerFileChooser();

    /**
     * Not to be invoked by clients.
     */
    private FileSupport() {
    }

    /**
     * Lets the user choose a directory with the JFileChooser.
     * 
     * @param parent
     *            the parent component for the FileChooser Dialog
     * @param titleText
     *            the title String for the dialog
     * @return null if it was canceled, otherwise the directory that was chosen
     */
    public File chooseDirectory(Component parent, String titleText) {
        File dir = null;
        getFileChooserOpenDat().setDialogTitle(titleText);
        getFileChooserOpenDat().setFileSelectionMode(
                JFileChooser.DIRECTORIES_ONLY);
        int returnVal = getFileChooserOpenDat().showOpenDialog(parent);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            dir = getFileChooserOpenDat().getSelectedFile();
        }
        return dir;

    }

    /**
     * @return javax.swing.JFileChooser
     */
    private javax.swing.JFileChooser getFileChooserOpenDat() {
        if (fileChooserOpenDat == null) {
            Object obj = fileChooserOpenDat_Worker.get();
            if (obj instanceof JFileChooser)
                fileChooserOpenDat = (JFileChooser) obj;
            else
                fileChooserOpenDat = new JFileChooser();
        }

        return fileChooserOpenDat;
    }

    /**
     * @return javax.swing.JFileChooser
     */
    private javax.swing.JFileChooser getFileChooserSave() {
        if (fileChooserSave == null) {
            Object obj = fileChooserSave_Worker.get();
            if (obj instanceof JFileChooser)
                fileChooserSave = (JFileChooser) obj;
            else
                fileChooserSave = new JFileChooser();
        }

        return fileChooserSave;
    }

    /**
     * Gets the Singleton instance of this class.
     * 
     * @return unique instance of FileSupport
     */
    public static FileSupport getInstance() {
        return fileSupport;
    }

    /**
     * Reads the contents of a text file and returns it as a string.
     * 
     * @param fileName
     *            of file ro read from
     * @return a string with the text of the file
     * @throws IllegalArgumentException
     *             if (fileName == null)
     */
    public String readTextFile(String fileName) {
        if (fileName == null)
            throw new IllegalArgumentException("Filename was null.");

        BufferedReader in = null;
        StringBuffer str = new StringBuffer();
        String tmp = null;
        try {
            in = new BufferedReader(new FileReader(fileName));
            while ((tmp = in.readLine()) != null)
                str.append(tmp + "\n");
            in.close();
        } catch (IOException e) {
            log.error("Error reading text from \"" + fileName + "\".", e);
            return "Error reading text from \"" + fileName + "\".";
        }
        return str.toString();
    }

    /**
     * Selects a data file for saving with a file chooser. The last selected
     * directory is displayed.
     * 
     * @param parent
     *            the parent component for the dialogs
     * @param filenameShort
     *            the selected filename without path, can be null
     * @param types
     *            the data handler types, the last element will be set as
     *            default
     * @return file if ok, null otherwise
     */
    public File saveDataFile(Component parent, String filenameShort,
            DataHandlerTypes... types) {
        if (filenameShort != null)
            filenameShort = filenameShort.trim();
        if (dataDirectory != null) {
            File dir = null;
            if (filenameShort == null || filenameShort.length() == 0) {
                dir = new File(dataDirectory);
                if (dir.isDirectory())
                    getFileChooserSave().setCurrentDirectory(dir);
            } else {
                dir = new File(dataDirectory + File.separator + filenameShort);
                getFileChooserSave().setSelectedFile(dir);
            }
        }

        getFileChooserSave().setDialogTitle("Save Data As ...");
        getFileChooserSave().resetChoosableFileFilters();

        // add other handlers only if false
        for (DataHandlerTypes type : types) {
            if (type.canWriteFormat())
                getFileChooserSave().addChoosableFileFilter(
                        type.getFileFilter());
        }
        if (currentSaveFilter != null)
            getFileChooserSave().setFileFilter(currentSaveFilter);

        getFileChooserSave().setMultiSelectionEnabled(false);
        getFileChooserSave().rescanCurrentDirectory();

        int returnVal = getFileChooserSave().showSaveDialog(parent);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = getFileChooserSave().getSelectedFile();
            if (file.getName().indexOf(".") < 1) {
                String ext = getSelectedSaveHandlerType().getFileExtension();
                file = new File(file.getAbsolutePath() + "." + ext);
            }
            // Ask before overwriting.
            if (file.exists()) {
                int accept = JOptionPane.showConfirmDialog(parent, "The file "
                        + file.getAbsolutePath()
                        + " already exists, overwrite?",
                        "Overwrite Existing File?", JOptionPane.YES_NO_OPTION);

                // Add the new time series to the time series table.
                if (accept == JOptionPane.NO_OPTION)
                    return null;
            }
            dataDirectory = file.getParent();
            currentSaveFilter = getFileChooserSave().getFileFilter();
            return file;
        }
        return null;

    }

    /**
     * Selects a project file for saving with a file chooser. The last selected
     * directory is displayed.
     * 
     * @param parent
     *            the parent component for the dialogs
     * @return file if ok, null otherwise
     */
    public File saveProjectFile(Component parent) {
        if (projectDirectory != null)
            getFileChooserSave()
                    .setCurrentDirectory(new File(projectDirectory));

        getFileChooserSave().setDialogTitle("Save Project As ...");
        getFileChooserSave().resetChoosableFileFilters();
        getFileChooserSave().addChoosableFileFilter(projectFileFilter);
        getFileChooserSave().setMultiSelectionEnabled(false);
        getFileChooserSave().rescanCurrentDirectory();
        if (projectFile != null)
            getFileChooserSave().setSelectedFile(new File(projectFile));

        int returnVal = getFileChooserSave().showSaveDialog(parent);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = getFileChooserSave().getSelectedFile();
            // Ask before overwriting.
            if (file.exists()) {
                int accept = JOptionPane.showConfirmDialog(parent, "The file "
                        + file.toString() + " already exists, overwrite?",
                        "Overwrite Existing File?", JOptionPane.YES_NO_OPTION);

                // Add the new time series to the time series table.
                if (accept == JOptionPane.NO_OPTION)
                    return null;
            }

            String fileName = file.toString();
            if (fileName.indexOf(".", fileName.lastIndexOf("/")) < 0) {
                fileName = fileName + ".jsc";
                file = new File(fileName);
            }
            projectDirectory = file.getParent();
            projectFile = file.getName();
            return file;
        }
        return null;

    }

    /**
     * Stores stringDat to file.
     * 
     * @param file
     *            the file to store stringDat to
     * @param stringDat
     *            the string to save
     * @param append
     *            true if string should be appended to existing
     *            file,
     * 
     */
    public void saveStringToFile(File file, String stringDat, boolean append) {
        if (file != null) {
            try {
                BufferedWriter out = new BufferedWriter(new FileWriter(file,
                        append));
                out.write(stringDat);
                out.flush();
                out.close();
            } catch (IOException ivjExc) {
                log.error("error saving data to file: "
                        + file.getAbsolutePath(), ivjExc);
            }

        }
    }

    /**
     * Selects a text file for saving with a file chooser. The last selected
     * directory is displayed.
     * 
     * @param parent
     *            the parent component for the dialogs
     * @return file if ok, null otherwise
     */
    public File saveTextFile(Component parent) {
        if (saveTextDirectory != null)
            getFileChooserSave().setCurrentDirectory(
                    new File(saveTextDirectory));

        getFileChooserSave().setDialogTitle("Save Results As ...");
        getFileChooserSave().resetChoosableFileFilters();
        getFileChooserSave().addChoosableFileFilter(textFileFilter);
        getFileChooserSave().setMultiSelectionEnabled(false);
        getFileChooserSave().rescanCurrentDirectory();

        int returnVal = getFileChooserSave().showSaveDialog(parent);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = getFileChooserSave().getSelectedFile();
            // Ask before overwriting.
            if (file.exists()) {
                int accept = JOptionPane.showConfirmDialog(parent, "The file "
                        + file.toString() + " already exists, overwrite?",
                        "Overwrite Existing File?", JOptionPane.YES_NO_OPTION);

                // Add the new time series to the time series table.
                if (accept == JOptionPane.NO_OPTION)
                    return null;

            }
            saveTextDirectory = file.getParent();
            return file;
        }
        return null;

    }

    /**
     * Selects a data file to open with a file chooser. The last selected
     * directory is displayed.
     * 
     * @param parent
     *            the parent component for the dialogs
     * @param types
     *            the data handler types, the last element will be set as
     *            default
     * @return file if ok, null otherwise
     */
    public File selectDataFile(Component parent, DataHandlerTypes... types) {
        if (dataDirectory == null) {
            if (new File(dataDirectory, "dataset").isDirectory())
                getFileChooserOpenDat().setCurrentDirectory(
                        new File(dataDirectory, "dataset"));
        } else
            getFileChooserOpenDat()
                    .setCurrentDirectory(new File(dataDirectory));

        getFileChooserOpenDat().setDialogTitle("Import Dataset");

        // initialize only once, selected import filter stays
        if (getFileChooserOpenDat().getChoosableFileFilters().length < 3) {
            getFileChooserOpenDat().resetChoosableFileFilters();
            for (DataHandlerTypes type : types) {
                getFileChooserOpenDat().addChoosableFileFilter(
                        type.getFileFilter());
            }
        }
        getFileChooserOpenDat().rescanCurrentDirectory();

        getFileChooserOpenDat().setMultiSelectionEnabled(false);

        int returnVal = getFileChooserOpenDat().showOpenDialog(parent);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = getFileChooserOpenDat().getSelectedFile();
            dataDirectory = file.getParent();
            return file;
        }
        return null;

    }

    /**
     * Selects a project file to open with a file chooser. The last selected
     * directory is displayed.
     * 
     * @param parent
     *            the parent component for the dialogs
     * @return file if ok, null otherwise
     */
    public File selectProjectFile(Component parent) {
        if (projectDirectory != null)
            getFileChooserOpenDat().setCurrentDirectory(
                    new File(projectDirectory));

        getFileChooserOpenDat().setDialogTitle("Open Project");
        getFileChooserOpenDat().resetChoosableFileFilters();
        getFileChooserOpenDat().addChoosableFileFilter(projectFileFilter);
        getFileChooserOpenDat().rescanCurrentDirectory();

        getFileChooserOpenDat().setMultiSelectionEnabled(false);

        int returnVal = getFileChooserOpenDat().showOpenDialog(parent);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = getFileChooserOpenDat().getSelectedFile();
            projectDirectory = file.getParent();
            projectFile = file.getName();
            return file;
        }
        return null;

    }

    /**
     * Sets the directory that will be displayed as default selection when a
     * file chooser is created. This should be set as program start. At further
     * invocations of the file choosers, the last selected directory will be
     * displayed.
     * 
     * @param newDefaultPath
     *            the new default path to be selected initially
     */
    public void setDefaultPath(String newDefaultPath) {
        dataDirectory = newDefaultPath;
        saveTextDirectory = newDefaultPath;
    }

    /**
     * Starts the SwingWorker threads to create
     * JFileChooser instances in the background.
     */
    public void startWorkers() {
        fileChooserOpenDat_Worker.start();
        fileChooserSave_Worker.start();
    }

    /**
     * Sets the selected files and directories to the settings argument. Nothing
     * happens if the argument is null or does not have at least
     * 6 rows.
     * 
     * @param settings
     *            holds the file parameters
     */
    public void setFileSupportSettings(FileSupportSettings settings) {
        if (settings == null)
            return;
        JSCSArray sel = settings.getSelectedFiles();
        if (sel.isEmpty() || sel.rows() < 4)
            return;
        saveTextDirectory = sel.stringAt(0, 0);
        dataDirectory = sel.stringAt(1, 0);
        projectFile = sel.stringAt(2, 0);
        projectDirectory = sel.stringAt(3, 0);
    }

    /**
     * Gets the settings instance according to the previously made file
     * selections.
     * 
     * @return settings instance
     */
    public FileSupportSettings getFileSupportSettings() {
        FileSupportSettings settings = new FileSupportSettings();
        JSCSArray sel = new JSCSArray("files",
                new String[] { saveTextDirectory, dataDirectory, projectFile,
                        projectDirectory });
        settings.setSelectedFiles(sel);
        return settings;
    }

    /**
     * Gets the handler type chosen for data import.
     * 
     * @return handler type
     */
    public DataHandlerTypes getSelectedImportHandlerType() {
        FileFilter filter = getFileChooserOpenDat().getFileFilter();
        DataHandlerTypes type = DataHandlerTypes.DAT; // default
        if (filter instanceof ExtensionFileFilter)
            type = ((ExtensionFileFilter) filter).getHandlerType();

        if (type == null)
            type = DataHandlerTypes.DAT;
        return type;
    }

    /**
     * Gets the handler type chosen for data export.
     * 
     * @return handler type
     */
    public DataHandlerTypes getSelectedSaveHandlerType() {
        FileFilter filter = getFileChooserSave().getFileFilter();
        DataHandlerTypes type = DataHandlerTypes.DAT; // default
        if (filter instanceof ExtensionFileFilter)
            type = ((ExtensionFileFilter) filter).getHandlerType();

        if (type == null)
            type = DataHandlerTypes.DAT;

        return type;

    }
}
 

Ads help maintain this website.