weka.gui.ConverterFileChooser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of weka-stable Show documentation
Show all versions of weka-stable Show documentation
The Waikato Environment for Knowledge Analysis (WEKA), a machine
learning workbench. This is the stable version. Apart from bugfixes, this version
does not receive any other updates.
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/*
* ConverterFileChooser.java
* Copyright (C) 2006-2012 University of Waikato, Hamilton, New Zealand
*/
package weka.gui;
import weka.core.Capabilities;
import weka.core.Instances;
import weka.core.converters.AbstractFileLoader;
import weka.core.converters.AbstractFileSaver;
import weka.core.converters.AbstractLoader;
import weka.core.converters.AbstractSaver;
import weka.core.converters.ConverterUtils;
import weka.core.converters.FileSourcedConverter;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.filechooser.FileFilter;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.Vector;
/**
* A specialized JFileChooser that lists all available file Loaders and Savers.
* To list only savers that can handle the data that is about to be saved, one
* can set a Capabilities filter.
*
* @author fracpete (fracpete at waikato dot ac dot nz)
* @version $Revision: 12161 $
* @see #setCapabilitiesFilter(Capabilities)
*/
public class ConverterFileChooser extends JFileChooser {
/** for serialization. */
private static final long serialVersionUID = -5373058011025481738L;
/** unhandled type of dialog. */
public final static int UNHANDLED_DIALOG = 0;
/** the loader dialog. */
public final static int LOADER_DIALOG = 1;
/** the saver dialog. */
public final static int SAVER_DIALOG = 2;
/** the file chooser itself. */
protected ConverterFileChooser m_Self;
/** the file filters for the loaders. */
protected static Vector m_LoaderFileFilters;
/** the file filters for the savers. */
protected static Vector m_SaverFileFilters;
/** the type of dialog to display. */
protected int m_DialogType;
/** the converter that was chosen by the user. */
protected Object m_CurrentConverter;
/** the configure button. */
protected JButton m_ConfigureButton;
/** the propertychangelistener. */
protected PropertyChangeListener m_Listener;
/** the last filter that was used for opening/saving. */
protected FileFilter m_LastFilter;
/** the Capabilities filter for the savers. */
protected Capabilities m_CapabilitiesFilter;
/**
* whether to popup a dialog in case the file already exists (only save
* dialog).
*/
protected boolean m_OverwriteWarning = true;
/** whether the file to be opened must exist (only open dialog). */
protected boolean m_FileMustExist = true;
/** the checkbox for bringing up the GenericObjectEditor. */
protected JCheckBox m_CheckBoxOptions;
/** the note about the options dialog. */
protected JLabel m_LabelOptions;
/** the GOE for displaying the options of a loader/saver. */
protected GenericObjectEditor m_Editor = null;
/** whether the GOE was OKed or Canceled. */
protected int m_EditorResult;
/**
* whether to display only core converters (hardcoded in ConverterUtils).
* Necessary for RMI/Remote Experiments for instance.
*
* @see ConverterUtils#CORE_FILE_LOADERS
* @see ConverterUtils#CORE_FILE_SAVERS
*/
protected boolean m_CoreConvertersOnly = false;
static {
initDefaultFilters();
}
/**
* Initialize the default set of filters for loaders and savers
*/
public static void initDefaultFilters() {
initFilters(true, ConverterUtils.getFileLoaders());
initFilters(false, ConverterUtils.getFileSavers());
}
/**
* onstructs a FileChooser pointing to the user's default directory.
*/
public ConverterFileChooser() {
super();
initialize();
}
/**
* Constructs a FileChooser using the given File as the path.
*
* @param currentDirectory the path to start in
*/
public ConverterFileChooser(File currentDirectory) {
super(currentDirectory);
initialize();
}
/**
* Constructs a FileChooser using the given path.
*
* @param currentDirectory the path to start in
*/
public ConverterFileChooser(String currentDirectory) {
super(currentDirectory);
initialize();
}
/**
* Further initializations.
*/
protected void initialize() {
JPanel panel;
JPanel panel2;
m_Self = this;
m_CheckBoxOptions = new JCheckBox("Invoke options dialog");
m_CheckBoxOptions.setMnemonic('I');
m_LabelOptions = new JLabel(
"
Note:
Some file formats offer additional
options which can be customized
when invoking the options dialog.");
panel = new JPanel(new BorderLayout());
panel.add(m_CheckBoxOptions, BorderLayout.NORTH);
panel2 = new JPanel(new BorderLayout());
panel2.add(m_LabelOptions, BorderLayout.NORTH);
panel2.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
panel.add(panel2, BorderLayout.CENTER);
setAccessory(panel);
m_Editor = new GenericObjectEditor(false);
((GenericObjectEditor.GOEPanel) m_Editor.getCustomEditor())
.addOkListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
m_EditorResult = JFileChooser.APPROVE_OPTION;
m_CurrentConverter = m_Editor.getValue();
// thanks to serialization and transient readers/streams, we have
// to set the file again to initialize the converter again
try {
((FileSourcedConverter) m_CurrentConverter)
.setFile(((FileSourcedConverter) m_CurrentConverter)
.retrieveFile());
} catch (Exception ex) {
// ignored
}
}
});
((GenericObjectEditor.GOEPanel) m_Editor.getCustomEditor())
.addCancelListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
m_EditorResult = JFileChooser.CANCEL_OPTION;
}
});
}
/**
* filters out all non-core loaders if only those should be displayed.
*
* @param list the list of filters to check
* @return the filtered list of filters
* @see #m_CoreConvertersOnly
*/
protected Vector filterNonCoreLoaderFileFilters(
Vector list) {
Vector result;
int i;
ExtensionFileFilter filter;
AbstractLoader loader;
if (!getCoreConvertersOnly()) {
result = list;
} else {
result = new Vector();
for (i = 0; i < list.size(); i++) {
filter = list.get(i);
loader = ConverterUtils
.getLoaderForExtension(filter.getExtensions()[0]);
if (ConverterUtils.isCoreFileLoader(loader.getClass().getName())) {
result.add(filter);
}
}
}
return result;
}
/**
* filters out all non-core savers if only those should be displayed.
*
* @param list the list of filters to check
* @return the filtered list of filters
* @see #m_CoreConvertersOnly
*/
protected Vector filterNonCoreSaverFileFilters(
Vector list) {
Vector result;
int i;
ExtensionFileFilter filter;
AbstractSaver saver;
if (!getCoreConvertersOnly()) {
result = list;
} else {
result = new Vector();
for (i = 0; i < list.size(); i++) {
filter = list.get(i);
saver = ConverterUtils.getSaverForExtension(filter.getExtensions()[0]);
if (ConverterUtils.isCoreFileSaver(saver.getClass().getName())) {
result.add(filter);
}
}
}
return result;
}
/**
* filters the list of file filters according to the currently set.
* Capabilities
*
* @param list the filters to check
* @return the filtered list of filters
*/
protected Vector filterSaverFileFilters(
Vector list) {
Vector result;
int i;
ExtensionFileFilter filter;
AbstractSaver saver;
if (m_CapabilitiesFilter == null) {
result = list;
} else {
result = new Vector();
for (i = 0; i < list.size(); i++) {
filter = list.get(i);
saver = ConverterUtils.getSaverForExtension(filter.getExtensions()[0]);
if (saver.getCapabilities().supports(m_CapabilitiesFilter)) {
result.add(filter);
}
}
}
return result;
}
/**
* initializes the ExtensionFileFilters.
*
* @param loader if true then the loader filter are initialized
* @param classnames the classnames of the converters
*/
protected static void initFilters(boolean loader, Vector classnames) {
int i;
int n;
String classname;
Class> cls;
String[] ext;
String desc;
FileSourcedConverter converter;
ExtensionFileFilter filter;
if (loader) {
m_LoaderFileFilters = new Vector();
} else {
m_SaverFileFilters = new Vector();
}
for (i = 0; i < classnames.size(); i++) {
classname = classnames.get(i);
// get data from converter
try {
cls = Class.forName(classname);
converter = (FileSourcedConverter) cls.newInstance();
ext = converter.getFileExtensions();
desc = converter.getFileDescription();
} catch (Exception e) {
cls = null;
converter = null;
ext = new String[0];
desc = "";
}
if (converter == null) {
continue;
}
// loader?
if (loader) {
for (n = 0; n < ext.length; n++) {
filter = new ExtensionFileFilter(ext[n], desc + " (*" + ext[n] + ")");
m_LoaderFileFilters.add(filter);
}
} else {
for (n = 0; n < ext.length; n++) {
filter = new ExtensionFileFilter(ext[n], desc + " (*" + ext[n] + ")");
m_SaverFileFilters.add(filter);
}
}
}
}
/**
* initializes the GUI.
*
* @param dialogType the type of dialog to setup the GUI for
*/
protected void initGUI(int dialogType) {
Vector list;
int i;
boolean acceptAll;
// backup current state
acceptAll = isAcceptAllFileFilterUsed();
// setup filters
resetChoosableFileFilters();
setAcceptAllFileFilterUsed(acceptAll);
if (dialogType == LOADER_DIALOG) {
list = filterNonCoreLoaderFileFilters(m_LoaderFileFilters);
} else {
list = filterSaverFileFilters(filterNonCoreSaverFileFilters(m_SaverFileFilters));
}
for (i = 0; i < list.size(); i++) {
addChoosableFileFilter(list.get(i));
}
if (list.size() > 0) {
if ((m_LastFilter == null) || (!list.contains(m_LastFilter))) {
setFileFilter(list.get(0));
} else {
setFileFilter(m_LastFilter);
}
}
// listener
if (m_Listener != null) {
removePropertyChangeListener(m_Listener);
}
m_Listener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
// filter changed
if (evt.getPropertyName().equals(FILE_FILTER_CHANGED_PROPERTY)) {
updateCurrentConverter();
}
}
};
addPropertyChangeListener(m_Listener);
// initial setup
if (dialogType == LOADER_DIALOG) {
m_Editor.setClassType(AbstractFileLoader.class);
m_Editor.setValue(new weka.core.converters.ArffLoader());
} else {
m_Editor.setClassType(AbstractFileSaver.class);
m_Editor.setValue(new weka.core.converters.ArffSaver());
}
updateCurrentConverter();
}
/**
* sets the capabilities that the savers must have. use null if all should be
* listed.
*
* @param value the minimum Capabilities the savers must have
*/
public void setCapabilitiesFilter(Capabilities value) {
m_CapabilitiesFilter = (Capabilities) value.clone();
}
/**
* returns the capabilities filter for the savers, can be null if all are
* listed.
*
* @return the minimum Capabilities the savers must have
*/
public Capabilities getCapabilitiesFilter() {
if (m_CapabilitiesFilter != null) {
return (Capabilities) m_CapabilitiesFilter.clone();
} else {
return null;
}
}
/**
* Whether a warning is popped up if the file that is to be saved already
* exists (only save dialog).
*
* @param value if true a warning will be popup
*/
public void setOverwriteWarning(boolean value) {
m_OverwriteWarning = value;
}
/**
* Returns whether a popup appears with a warning that the file already exists
* (only save dialog).
*
* @return true if a warning pops up
*/
public boolean getOverwriteWarning() {
return m_OverwriteWarning;
}
/**
* Whether the selected file must exst (only open dialog).
*
* @param value if true the file must exist
*/
public void setFileMustExist(boolean value) {
m_FileMustExist = value;
}
/**
* Returns whether the selected file must exist (only open dialog).
*
* @return true if the file must exist
*/
public boolean getFileMustExist() {
return m_FileMustExist;
}
/**
* Whether to display only the hardocded core converters. Necessary for
* RMI/Remote Experiments (dynamic class discovery doesn't work there!).
*
* @param value if true only the core converters will be displayed
* @see #m_CoreConvertersOnly
*/
public void setCoreConvertersOnly(boolean value) {
m_CoreConvertersOnly = value;
}
/**
* Returns whether only the hardcoded core converters are displayed. Necessary
* for RMI/REmote Experiments (dynamic class discovery doesn't work there!).
*
* @return true if the file must exist
* @see #m_CoreConvertersOnly
*/
public boolean getCoreConvertersOnly() {
return m_CoreConvertersOnly;
}
/**
* Pops a custom file chooser dialog with a custom approve button. Throws an
* exception, if the dialog type is UNHANDLED_DIALOG.
*
* @param parent the parent of this dialog
* @param approveButtonText the text for the OK button
* @return the user's action
*/
@Override
public int showDialog(Component parent, String approveButtonText) {
if (m_DialogType == UNHANDLED_DIALOG) {
throw new IllegalStateException(
"Either use showOpenDialog or showSaveDialog!");
} else {
return super.showDialog(parent, approveButtonText);
}
}
/**
* Pops up an "Open File" file chooser dialog.
*
* @param parent the parent of this file chooser
* @return the result of the user's action
*/
@Override
public int showOpenDialog(Component parent) {
m_DialogType = LOADER_DIALOG;
m_CurrentConverter = null;
initGUI(LOADER_DIALOG);
int result = super.showOpenDialog(parent);
m_DialogType = UNHANDLED_DIALOG;
removePropertyChangeListener(m_Listener);
// do we have to add the extension?
if ((result == APPROVE_OPTION) && (getSelectedFile().isFile())) {
if (getFileFilter() instanceof ExtensionFileFilter) {
String filename = getSelectedFile().getAbsolutePath();
String[] extensions = ((ExtensionFileFilter) getFileFilter())
.getExtensions();
if (!filename.endsWith(extensions[0])) {
filename += extensions[0];
setSelectedFile(new File(filename));
}
}
}
// does file exist?
if ((result == APPROVE_OPTION) && (getFileMustExist())
&& (getSelectedFile().isFile()) && (!getSelectedFile().exists())) {
int retVal = JOptionPane.showConfirmDialog(parent, "The file '"
+ getSelectedFile() + "' does not exist - please select again!");
if (retVal == JOptionPane.OK_OPTION) {
result = showOpenDialog(parent);
} else {
result = CANCEL_OPTION;
}
}
if (result == APPROVE_OPTION) {
m_LastFilter = getFileFilter();
configureCurrentConverter(LOADER_DIALOG);
// bring up options dialog?
if (m_CheckBoxOptions.isSelected() && m_CurrentConverter != null) {
m_EditorResult = JFileChooser.CANCEL_OPTION;
m_Editor.setValue(m_CurrentConverter);
PropertyDialog pd;
if (PropertyDialog.getParentDialog(this) != null) {
pd = new PropertyDialog(PropertyDialog.getParentDialog(this),
m_Editor);
} else {
pd = new PropertyDialog(PropertyDialog.getParentFrame(this), m_Editor);
}
pd.setVisible(true);
result = m_EditorResult;
}
}
return result;
}
/**
* Pops up an "Save File" file chooser dialog.
*
* @param parent the parent of this file chooser
* @return the result of the user's action
*/
@Override
public int showSaveDialog(Component parent) {
m_DialogType = SAVER_DIALOG;
m_CurrentConverter = null;
initGUI(SAVER_DIALOG);
boolean acceptAll = isAcceptAllFileFilterUsed();
// using "setAcceptAllFileFilterUsed" messes up the currently selected
// file filter/file, hence backup/restore of currently selected
// file filter/file
FileFilter currentFilter = getFileFilter();
File currentFile = getSelectedFile();
setAcceptAllFileFilterUsed(false);
setFileFilter(currentFilter);
setSelectedFile(currentFile);
int result = super.showSaveDialog(parent);
// do we have to add the extension?
if (result == APPROVE_OPTION) {
if (getFileFilter() instanceof ExtensionFileFilter) {
String filename = getSelectedFile().getAbsolutePath();
String[] extensions = ((ExtensionFileFilter) getFileFilter())
.getExtensions();
if (!filename.endsWith(extensions[0])) {
filename += extensions[0];
setSelectedFile(new File(filename));
}
}
}
// using "setAcceptAllFileFilterUsed" messes up the currently selected
// file filter/file, hence backup/restore of currently selected
// file filter/file
currentFilter = getFileFilter();
currentFile = getSelectedFile();
setAcceptAllFileFilterUsed(acceptAll);
setFileFilter(currentFilter);
setSelectedFile(currentFile);
m_DialogType = UNHANDLED_DIALOG;
removePropertyChangeListener(m_Listener);
// overwrite the file?
if ((result == APPROVE_OPTION) && (getOverwriteWarning())
&& (getSelectedFile().exists())) {
int retVal = JOptionPane.showConfirmDialog(parent, "The file '"
+ getSelectedFile() + "' already exists - overwrite it?");
if (retVal == JOptionPane.OK_OPTION) {
result = APPROVE_OPTION;
} else if (retVal == JOptionPane.NO_OPTION) {
result = showSaveDialog(parent);
} else {
result = CANCEL_OPTION;
}
}
if (result == APPROVE_OPTION) {
m_LastFilter = getFileFilter();
// configureCurrentConverter(SAVER_DIALOG);
// bring up options dialog?
if (m_CheckBoxOptions.isSelected()) {
m_EditorResult = JFileChooser.CANCEL_OPTION;
m_Editor.setValue(m_CurrentConverter);
PropertyDialog pd;
if (PropertyDialog.getParentDialog(this) != null) {
pd = new PropertyDialog(PropertyDialog.getParentDialog(this),
m_Editor);
} else {
pd = new PropertyDialog(PropertyDialog.getParentFrame(this), m_Editor);
}
pd.setVisible(true);
result = m_EditorResult;
// configureCurrentConverter(SAVER_DIALOG);
}
}
return result;
}
/**
* returns the loader that was chosen by the user, can be null in case the
* user aborted the dialog or the save dialog was shown.
*
* @return the chosen loader, if any
*/
public AbstractFileLoader getLoader() {
configureCurrentConverter(LOADER_DIALOG);
if (m_CurrentConverter instanceof AbstractFileSaver) {
return null;
} else {
return (AbstractFileLoader) m_CurrentConverter;
}
}
/**
* returns the saver that was chosen by the user, can be null in case the user
* aborted the dialog or the open dialog was shown.
*
* @return the chosen saver, if any
*/
public AbstractFileSaver getSaver() {
configureCurrentConverter(SAVER_DIALOG);
if (m_CurrentConverter instanceof AbstractFileLoader) {
return null;
} else {
return (AbstractFileSaver) m_CurrentConverter;
}
}
/**
* sets the current converter according to the current filefilter.
*/
protected void updateCurrentConverter() {
String[] extensions;
Object newConverter;
if (getFileFilter() == null) {
return;
}
if (!isAcceptAllFileFilterUsed()) {
// determine current converter
extensions = ((ExtensionFileFilter) getFileFilter()).getExtensions();
if (m_DialogType == LOADER_DIALOG) {
newConverter = ConverterUtils.getLoaderForExtension(extensions[0]);
} else {
newConverter = ConverterUtils.getSaverForExtension(extensions[0]);
}
try {
if (m_CurrentConverter == null) {
m_CurrentConverter = newConverter;
} else {
if (!m_CurrentConverter.getClass().equals(newConverter.getClass())) {
m_CurrentConverter = newConverter;
}
}
} catch (Exception e) {
m_CurrentConverter = null;
e.printStackTrace();
}
} else {
m_CurrentConverter = null;
}
}
/**
* configures the current converter.
*
* @param dialogType the type of dialog to configure for
*/
protected void configureCurrentConverter(int dialogType) {
String filename;
File currFile;
if ((getSelectedFile() == null) || (getSelectedFile().isDirectory())) {
return;
}
filename = getSelectedFile().getAbsolutePath();
if (m_CurrentConverter == null) {
if (dialogType == LOADER_DIALOG) {
m_CurrentConverter = ConverterUtils.getLoaderForFile(filename);
} else if (dialogType == SAVER_DIALOG) {
m_CurrentConverter = ConverterUtils.getSaverForFile(filename);
} else {
throw new IllegalStateException("Cannot determine loader/saver!");
}
// none found?
if (m_CurrentConverter == null) {
return;
}
}
try {
currFile = ((FileSourcedConverter) m_CurrentConverter).retrieveFile();
if ((currFile == null) || (!currFile.getAbsolutePath().equals(filename))) {
((FileSourcedConverter) m_CurrentConverter).setFile(new File(filename));
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* For testing the file chooser.
*
* @param args the commandline options - ignored
* @throws Exception if something goes wrong with loading/saving
*/
public static void main(String[] args) throws Exception {
ConverterFileChooser fc;
int retVal;
AbstractFileLoader loader;
AbstractFileSaver saver;
Instances data;
fc = new ConverterFileChooser();
retVal = fc.showOpenDialog(null);
// load file
if (retVal == ConverterFileChooser.APPROVE_OPTION) {
loader = fc.getLoader();
data = loader.getDataSet();
retVal = fc.showSaveDialog(null);
// save file
if (retVal == ConverterFileChooser.APPROVE_OPTION) {
saver = fc.getSaver();
saver.setInstances(data);
saver.writeBatch();
} else {
System.out.println("Saving aborted!");
}
} else {
System.out.println("Loading aborted!");
}
}
}