blob: a7a51be163edeacb3b387cfc83a73f21aa5a634f [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2007 The University of Manchester
*
* Modifications to the initial code base are copyright of their
* respective authors, or their employers as appropriate.
*
* This program 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 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
******************************************************************************/
package net.sf.taverna.t2.reference.ui.referenceactions;
import static java.lang.System.getProperty;
import static javax.swing.JFileChooser.APPROVE_OPTION;
import static javax.swing.JFileChooser.FILES_ONLY;
import static javax.swing.JOptionPane.ERROR_MESSAGE;
import static javax.swing.JOptionPane.YES_NO_OPTION;
import static javax.swing.JOptionPane.YES_OPTION;
import static javax.swing.JOptionPane.showConfirmDialog;
import static javax.swing.JOptionPane.showMessageDialog;
import static net.sf.taverna.t2.baclava.factory.DataThingFactory.bake;
import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.xmlNodeIcon;
import static org.jdom.Namespace.getNamespace;
import static org.jdom.output.Format.getPrettyFormat;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.prefs.Preferences;
import javax.swing.AbstractAction;
import javax.swing.JFileChooser;
import net.sf.taverna.t2.baclava.DataThing;
import net.sf.taverna.t2.invocation.InvocationContext;
import net.sf.taverna.t2.lang.ui.ExtensionFileFilter;
import net.sf.taverna.t2.reference.ui.RegistrationPanel;
import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.output.XMLOutputter;
/**
* Stores the entire map of result objects to disk
* as a single XML data document.
*
* @author Tom Oinn
* @author Alex Nenadic
*/
public class SaveInputsAsXML extends AbstractAction implements ReferenceActionSPI {
private static final long serialVersionUID = 452360182978773176L;
private static final String INPUT_DATA_DIR_PROPERTY = "inputDataValuesDir";
private static final Logger logger = Logger
.getLogger(SaveInputsAsXML.class);
public static final String BACLAVA_NAMESPACE = "http://org.embl.ebi.escience/baclava/0.1alpha";
/** {@value #BACLAVA_NAMESPACE} */
private static final Namespace namespace = getNamespace("b",
BACLAVA_NAMESPACE);
@SuppressWarnings("unused")
private InvocationContext context = null;
private Map<String, RegistrationPanel> inputPanelMap;
public SaveInputsAsXML(){
super();
putValue(NAME, "Save values");
putValue(SMALL_ICON, xmlNodeIcon);
}
@Override
public AbstractAction getAction() {
return new SaveInputsAsXML();
}
// Must be called before actionPerformed()
public void setInvocationContext(InvocationContext context) {
this.context = context;
}
/**
* Shows a standard save dialog and dumps the entire input set to the
* specified XML file.
*/
@Override
public void actionPerformed(ActionEvent e) {
Preferences prefs = Preferences.userNodeForPackage(getClass());
String curDir = prefs.get(INPUT_DATA_DIR_PROPERTY, getProperty("user.home"));
JFileChooser fc = new JFileChooser();
fc.setDialogTitle("Select file to save input values to");
fc.resetChoosableFileFilters();
fc.setFileFilter(new ExtensionFileFilter(new String[] { "xml" }));
fc.setCurrentDirectory(new File(curDir));
fc.setFileSelectionMode(FILES_ONLY);
File file;
do {
if (fc.showSaveDialog(null) != APPROVE_OPTION)
return;
prefs.put(INPUT_DATA_DIR_PROPERTY, fc.getCurrentDirectory().toString());
file = fc.getSelectedFile();
/*
* If the user did not use the .xml extension for the file - append
* it to the file name now
*/
if (!file.getName().toLowerCase().endsWith(".xml"))
file = new File(file.getParentFile(), file.getName() + ".xml");
// If the file exists, ask the user if they want to overwrite the file
} while (file.exists()
&& showConfirmDialog(null, file.getAbsolutePath()
+ " already exists. Do you want to overwrite it?",
"File already exists", YES_NO_OPTION) != YES_OPTION);
doSave(file);
}
private void doSave(final File file) {
// Do this in separate thread to avoid hanging UI
new Thread("Save(InputsAsXML: Saving inputs to " + file) {
@Override
public void run() {
try {
synchronized (inputPanelMap) {
saveData(file);
}
} catch (Exception ex) {
showMessageDialog(null, "Problem saving input data",
"Save Inputs Error", ERROR_MESSAGE);
logger.error("Problem saving input data as XML", ex);
}
}
}.start();
}
/**
* Saves the input data to an XML Baclava file.
*/
private void saveData(File file) throws Exception {
// Build the DataThing map from the inputPanelMap
Map<String, Object> valueMap = new HashMap<>();
for (String portName : inputPanelMap.keySet()) {
RegistrationPanel panel = inputPanelMap.get(portName);
Object obj = panel.getValue();
if (obj != null)
valueMap.put(portName, obj);
}
Map<String, DataThing> dataThings = bakeDataThingMap(valueMap);
// Build the string containing the XML document from the panel map
String xmlString = new XMLOutputter(getPrettyFormat())
.outputString(getDataDocument(dataThings));
try (PrintWriter out = new PrintWriter(new FileWriter(file))) {
out.print(xmlString);
}
}
/**
* Returns a map of port names to DataThings from a map of port names to a
* list of (lists of ...) result objects.
*/
Map<String, DataThing> bakeDataThingMap(Map<String, Object> resultMap) {
Map<String, DataThing> dataThingMap = new HashMap<>();
for (String portName : resultMap.keySet())
dataThingMap.put(portName, bake(resultMap.get(portName)));
return dataThingMap;
}
/**
* Returns a org.jdom.Document from a map of port named to DataThingS containing
* the port's results.
*/
public static Document getDataDocument(Map<String, DataThing> dataThings) {
Element rootElement = new Element("dataThingMap", namespace);
Document theDocument = new Document(rootElement);
for (String key : dataThings.keySet()) {
DataThing value = (DataThing) dataThings.get(key);
Element dataThingElement = new Element("dataThing", namespace);
dataThingElement.setAttribute("key", key);
dataThingElement.addContent(value.getElement());
rootElement.addContent(dataThingElement);
}
return theDocument;
}
@Override
public void setInputPanelMap(Map<String, RegistrationPanel> inputPanelMap) {
this.inputPanelMap = inputPanelMap;
}
}