/*
* The University of Wales, Cardiff Triana Project Software License (Based
* on the Apache Software License Version 1.1)
*
* Copyright (c) 2007 University of Wales, Cardiff. All rights reserved.
*
* Redistribution and use of the software in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The end-user documentation included with the redistribution, if any,
* must include the following acknowledgment: "This product includes
* software developed by the University of Wales, Cardiff for the Triana
* Project (http://www.trianacode.org)." Alternately, this
* acknowledgment may appear in the software itself, if and wherever
* such third-party acknowledgments normally appear.
*
* 4. The names "Triana" and "University of Wales, Cardiff" must not be
* used to endorse or promote products derived from this software
* without prior written permission. For written permission, please
* contact triana@trianacode.org.
*
* 5. Products derived from this software may not be called "Triana," nor
* may Triana appear in their name, without prior written permission of
* the University of Wales, Cardiff.
*
* 6. This software may not be sold, used or incorporated into any product
* for sale to third parties.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL UNIVERSITY OF WALES, CARDIFF OR ITS CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* ------------------------------------------------------------------------
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Triana Project. For more information on the
* Triana Project, please see. http://www.trianacode.org.
*
* This license is based on the BSD license as adopted by the Apache
* Foundation and is governed by the laws of England and Wales.
*
*/
package org.trianacode.gui.action.files;
import org.trianacode.gui.Display;
import org.trianacode.gui.TrianaDialog;
import org.trianacode.gui.action.SelectionManager;
import org.trianacode.gui.extensions.FileImportExportDecorator;
import org.trianacode.gui.hci.GUIEnv;
import org.trianacode.gui.hci.TrianaProgressBar;
import org.trianacode.gui.panels.ParameterPanel;
import org.trianacode.gui.panels.ParameterPanelImp;
import org.trianacode.gui.panels.TFileChooser;
import org.trianacode.gui.panels.ToolPanel;
import org.trianacode.gui.util.Env;
import org.trianacode.gui.windows.ErrorDialog;
import org.trianacode.gui.windows.ParameterWindow;
import org.trianacode.gui.windows.SaveToolDialog;
import org.trianacode.gui.windows.WindowButtonConstants;
import org.trianacode.taskgraph.TaskGraph;
import org.trianacode.taskgraph.TaskGraphException;
import org.trianacode.taskgraph.ser.XMLReader;
import org.trianacode.taskgraph.ser.XMLWriter;
import org.trianacode.taskgraph.tool.Tool;
import org.trianacode.taskgraph.tool.ToolTable;
import org.trianacode.taskgraph.util.UrlUtils;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import javax.swing.plaf.basic.BasicFileChooserUI;
import java.awt.*;
import java.io.*;
import java.net.URL;
import java.util.StringTokenizer;
/**
* A class to handle the loading and saving of TaskGraph files.
*
* @author Matthew Shields
* @version $Revision: 4051 $
*/
public class TaskGraphFileHandler implements SelectionManager {
private static String IMPORT_TOOL_DIR = "importToolFrom";
private static String IMPORT_TASKGRAPH_DIR = "importTaskGraphFrom";
private static String EXPORT_TASKGRAPH_DIR = "exportTaskGraphTo";
public TaskGraphFileHandler() {
}
/**
* @return The object that is selected for this handler.
*/
public Object getSelectionHandler() {
return this;
}
/**
* Save a taskgraph/group to a file.
*
* @param task The Triana Tool object we want to save
* @param file the file to save to
* @param tools The tooltable (can be null)
* @param updateRecent if true then the file is added to the recent items list
*/
public static boolean saveTaskGraphAs(final Tool task, final String file, final ToolTable tools,
final boolean updateRecent) {
boolean b = true;
XMLWriter writer = null;
try {
BufferedWriter fileWriter = new BufferedWriter(new FileWriter(file));
writer = new XMLWriter(fileWriter);
writer.writeComponent(task);
if (tools != null) {
tools.refreshLocation(new File(file).toURI().toURL(), null);
}
if (updateRecent) {
GUIEnv.getApplicationFrame().getTrianaMenuBar().updateRecentMenu(file);
}
} catch (IOException e) {
b = false;
e.printStackTrace(System.out);
} finally {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace(System.out);
b = false;
}
}
return b;
}
/**
* Load a taskgraph from a file
*
* @param file the file to load from
*/
public static void backgroundOpenTaskgraph(final File file) {
backgroundOpenTaskgraph(file, true);
}
/**
* Open a group from file/network/toolbox or view a group on a MainTriana.
*/
public static void open() {
File selectedFile = selectFile();
if (selectedFile != null) {
backgroundOpenTaskgraph(selectedFile);
}
}
private static File selectFile() {
TFileChooser chooser = new TFileChooser(Env.TASKGRAPH_DIRECTORY);
chooser.setDialogTitle("Open TaskGraph");
chooser.setMultiSelectionEnabled(false);
chooser.setFileFilter(new XMLFileFilter());
int result = chooser.showOpenDialog(GUIEnv.getApplicationFrame());
File selectedFile = null;
if (result == JFileChooser.APPROVE_OPTION) {
selectedFile = chooser.getSelectedFile();
}
return selectedFile;
}
public static TaskGraph openTaskgraph(final File file, final boolean updateRecent) {
return openTaskGraph(file, updateRecent, true);
}
/**
* Open a taskgraph file and render it.
*
* @param file the file which the taskgraph is to be loaded from
* @param updateRecent update the recently opened menu item
* @param runnable if false then the taskgraph is non-runnable, used for debugging or visualisation
* @return a reference to the loaded taskgraph
*/
private static TaskGraph openTaskGraph(File file, boolean updateRecent, boolean runnable) {
XMLReader reader = null;
TrianaProgressBar progressBar = null;
try {
BufferedReader filereader = new BufferedReader(new FileReader(file));
reader = new XMLReader(filereader);
if (updateRecent) {
GUIEnv.getApplicationFrame().getTrianaMenuBar().updateRecentMenu(file.getAbsolutePath());
}
} catch (IOException e) {
System.out.println(file + " : not found");
}
try {
Tool tool = reader.readComponent(GUIEnv.getApplicationFrame().getEngine().getProperties());
if (tool instanceof TaskGraph) {
progressBar = new TrianaProgressBar("loading: " + file.getName(), false);
tool.setDefinitionPath(file.toURI().toURL());
TaskGraph initgraph = null;
if (runnable) {
initgraph = GUIEnv.getApplicationFrame().addParentTaskGraphPanel((TaskGraph) tool);
} else {
initgraph = GUIEnv.getApplicationFrame().addNoExecParentTaskGraphPanel((TaskGraph) tool);
}
return initgraph;
} else {
JOptionPane.showMessageDialog(GUIEnv.getApplicationFrame(),
"Error: " + file.getName() + " is not a valid taskgraph file", "Open Error",
JOptionPane.ERROR_MESSAGE, GUIEnv.getTrianaIcon());
}
} catch (TaskGraphException except) {
new ErrorDialog(Env.getString("inputError"), except.getMessage());
} catch (IOException e) {
System.err.println(e.getMessage() + " in file: " + file);
e.printStackTrace(System.out);
} finally {
if (progressBar != null) {
progressBar.disposeProgressBar();
}
try {
reader.close();
} catch (IOException e) {
e.printStackTrace(System.out);
}
}
return null;
}
private static void backgroundOpenTaskgraph(final File file, final boolean updateRecent) {
Thread thread = new Thread() {
public void run() {
openTaskgraph(file, updateRecent);
}
};
thread.setName("TaskGraphLoader" + file);
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
/**
* Show the import file dialog and import the workflow/task graph using the selected
* <code>FileImportExportDecorator.importWorkflow</code> method.
*/
public static void importTaskgraph() {
final TFileChooser fc = new TFileChooser(IMPORT_TASKGRAPH_DIR);
final FileImportExportDecorator chooser = new FileImportExportDecorator(fc);
int result = chooser.showImportDialog(GUIEnv.getApplicationFrame());
if (result == TFileChooser.APPROVE_OPTION) {
Thread thread = new Thread() {
public void run() {
TrianaProgressBar progressBar = null;
String filename = "";
try {
filename = fc.getSelectedFile().getName();
progressBar = new TrianaProgressBar("loading: " + filename, false);
GUIEnv.getApplicationFrame().addParentTaskGraphPanel(chooser.importWorkflow());
} catch (TaskGraphException except) {
new ErrorDialog(Env.getString("inputError"), except.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage() + " in file: " + filename);
e.printStackTrace(System.out);
} finally {
if (progressBar != null) {
progressBar.disposeProgressBar();
}
}
}
};
thread.setName("Import Task Graph");
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
}
/**
* Show the export file dialog and export the current selected task graph using the selected
* <code>FileImportExportDecorator.exportWorkflow</code> method.
*/
public static void exportTaskgraph() {
final TFileChooser fc = new TFileChooser(EXPORT_TASKGRAPH_DIR);
final FileImportExportDecorator chooser = new FileImportExportDecorator(fc);
int result = chooser.showExportDialog(GUIEnv.getApplicationFrame());
if (result == TFileChooser.APPROVE_OPTION) {
Thread thread = new Thread() {
public void run() {
TrianaProgressBar pb = null;
String filename = "";
try {
// Bug fix for not picking up file name text.
if (fc.getUI() instanceof BasicFileChooserUI) {
filename = ((BasicFileChooserUI) fc.getUI()).getFileName();
}
pb = new TrianaProgressBar("exporting: " + filename, false);
chooser.exportWorkflow(GUIEnv.getApplicationFrame().getSelectedTaskGraphPanel().getTaskGraph());
} catch (IOException e) {
ErrorDialog.show("Error Exporting TaskGraph", e.getMessage());
e.printStackTrace();
} catch (TaskGraphException e) {
ErrorDialog.show("Error Exporting TaskGraph", e.getMessage());
e.printStackTrace();
} finally {
if (pb != null) {
pb.disposeProgressBar();
}
}
}
};
thread.setName("Export Task Graph");
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
}
/**
* Show the import fie dialog and import the tools from the selected file using the selected
* <code>FileImportExportDecorator.importTools</code> method. The imported tools are saved to the user selected
* toolbox in Triana format.
*
* @param tooltable
*/
public void importTools(final ToolTable tooltable) {
final TFileChooser fc = new TFileChooser(IMPORT_TOOL_DIR);
final FileImportExportDecorator chooser = new FileImportExportDecorator(fc);
int result = chooser.showImportToolDialog(GUIEnv.getApplicationFrame());
if (result == TFileChooser.APPROVE_OPTION) {
final ImportInfoHandler handler = new ImportInfoHandler(tooltable, chooser.getDefaultToolPackage());
if (handler.isApproved()) {
Thread thread = new Thread() {
public void run() {
TrianaProgressBar progressBar = null;
String filename = "";
try {
filename = fc.getSelectedFile().getName();
progressBar = new TrianaProgressBar("loading: " + filename, false);
Tool[] tools = chooser.importTools(handler.getPackage());
for (int i = 0; i < tools.length; i++) {
Tool tool = tools[i];
XMLWriter writer = null;
String dir = handler.getToolBox() + Env.separator() + tool.getToolPackage().replace('.',
File.separatorChar);
File f = new File(dir);
if (f.exists() || f.mkdirs()) {
try {
String toolfile = dir + Env.separator() + tool.getToolName() + ".xml";
if (TrianaDialog.isOKtoWriteIfExists(toolfile)) {
f = new File(toolfile);
BufferedWriter fileWriter = new BufferedWriter(new FileWriter(f));
writer = new XMLWriter(fileWriter);
writer.writeComponent(tool);
tooltable.refreshLocation(UrlUtils.toURL(toolfile), handler.getToolBox());
}
} catch (IOException e) {
e.printStackTrace(System.out);
}
}
}
} catch (TaskGraphException except) {
new ErrorDialog(Env.getString("inputError"), except.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage() + " in file: " + filename);
e.printStackTrace(System.out);
} finally {
if (progressBar != null) {
progressBar.disposeProgressBar();
}
}
}
};
thread.setName("Import Tools");
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
}
}
/**
* rudimentary at the moment just pops up a dialog, no checking to see if this is an existing group that has been
* modified
*/
public static boolean saveTaskGraph(TaskGraph taskgraph, ToolTable tools, boolean saveas) {
TaskGraph group = taskgraph;
if (group.getParent() != null) {
TaskGraph parent = group.getParent();
while (parent.getParent() != null) {
parent = parent.getParent();
}
String[] options = new String[]{group.getToolName(), parent.getToolName() + " (root)", "Cancel"};
String title = "Save...";
if (saveas) {
title = "Save As...";
}
int choice = JOptionPane.showOptionDialog(GUIEnv.getApplicationFrame(),
"Save current group or root taskgraph?", title, JOptionPane.DEFAULT_OPTION,
JOptionPane.QUESTION_MESSAGE, GUIEnv.getTrianaIcon(), options, options[0]);
if (choice == 1) {
group = parent;
} else if (choice == 2) {
return false;
}
}
URL definitionPath = group.getDefinitionPath();
boolean showdialog = saveas || (definitionPath == null) || (definitionPath.equals("") || !group
.getDefinitionType().equals(Tool.DEFINITION_TRIANA_XML));
boolean writeFile = true;
if (showdialog) {
writeFile = false;
SaveToolDialog dialog = new SaveToolDialog(group, tools);
if (dialog.isGo()) {
String toolbox = group.getToolBox().getPath();
File tb = new File(toolbox);
File out = getOutputFile(tb, group.getToolPackage());
definitionPath = UrlUtils.toURL(out.getAbsolutePath() + File.separator + group.getToolName() + ".xml");
group.setDefinitionPath(definitionPath);
if (TrianaDialog.isOKtoWriteIfExists(definitionPath.getPath())) {
writeFile = true;
} else {
writeFile = false;
}
}
}
if (writeFile) {
backGroundSaveTaskGraph(taskgraph, definitionPath.getPath(), tools, true);
}
return writeFile;
}
/**
* rudimentary at the moment just pops up a dialog, no checking to see if this is an existing group that has been
* modified
*/
public static boolean saveTaskGraphAsFile(TaskGraph taskgraph, ToolTable tools) {
TaskGraph group = taskgraph;
if (group.getParent() != null) {
TaskGraph parent = group.getParent();
while (parent.getParent() != null) {
parent = parent.getParent();
}
String[] options = new String[]{group.getToolName(), parent.getToolName() + " (root)", "Cancel"};
String
title = "Save As...";
int choice = JOptionPane.showOptionDialog(GUIEnv.getApplicationFrame(),
"Save current group or root taskgraph?", title, JOptionPane.DEFAULT_OPTION,
JOptionPane.QUESTION_MESSAGE, GUIEnv.getTrianaIcon(), options, options[0]);
if (choice == 1) {
group = parent;
} else if (choice == 2) {
return false;
}
}
boolean writeFile = false;
TFileChooser chooser = new TFileChooser(System.getProperty("user.dir"));
chooser.setMultiSelectionEnabled(false);
int result = chooser.showSaveDialog(GUIEnv.getApplicationFrame());
if (result == TFileChooser.APPROVE_OPTION) {
File f = chooser.getSelectedFile();
if (f != null) {
if (taskgraph.getToolName().startsWith("Untitled")) {
taskgraph.setToolName(f.getName());
}
backGroundSaveTaskGraph(taskgraph, f.getAbsolutePath(), tools, true);
writeFile = true;
}
}
return writeFile;
}
private static File getOutputFile(File toolbox, String pkg) {
File root = toolbox;
root.mkdirs();
File curr = new File(root, "xml");
curr.mkdirs();
StringTokenizer st = new StringTokenizer(pkg, ".", false);
while (st.hasMoreTokens()) {
String tok = st.nextToken();
curr = new File(curr, tok);
curr.mkdirs();
}
return curr;
}
private static void backGroundSaveTaskGraph(final Tool task, final String file, final ToolTable tools,
final boolean updateRecent) {
Thread thread = new Thread() {
public void run() {
saveTaskGraphAs(task, file, tools, updateRecent);
}
};
thread.setName("Load TaskGraph: " + file);
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
/**
* Utility method for opening a non-functioning taskgraph for display purposes only
*/
public static void openForDisplayOnly() {
final File selectedFile = selectFile();
if (selectedFile != null) {
Thread thread = new Thread() {
public void run() {
openTaskGraph(selectedFile, false, false);
}
};
thread.setName("Load TaskGraph: " + selectedFile);
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
}
private static class XMLFileFilter extends FileFilter {
private static final String XML_EXTENSION = ".xml";
/**
* Whether the given file is accepted by this filter.
*/
public boolean accept(File file) {
return file.isDirectory() || file.getName().toLowerCase().endsWith(XML_EXTENSION);
}
/**
* The description of this filter. For example: "JPG and GIF Images"
*
* @see javax.swing.filechooser.FileView#getName
*/
public String getDescription() {
return "XML Files";
}
}
private class ImportInfoHandler {
private ToolPanel toolpanel;
private ParameterWindow window;
public ImportInfoHandler(ToolTable tools, String defpack) {
toolpanel = new ToolPanel(tools, false);
toolpanel.setPackage(defpack);
ParameterPanel panel = new ParameterPanelImp();
panel.setLayout(new BorderLayout());
panel.add(toolpanel, BorderLayout.CENTER);
window = new ParameterWindow(GUIEnv.getApplicationFrame(), WindowButtonConstants.OK_CANCEL_BUTTONS, true);
window.setTitle("Import Into...");
window.setParameterPanel(panel);
Display.centralise(window);
window.setVisible(true);
}
public boolean isApproved() {
return window.isAccepted();
}
public String getPackage() {
return toolpanel.getPackage();
}
public String getToolBox() {
return toolpanel.getToolBox();
}
}
}