package au.com.acpfg.misc.jemboss.settings; import java.awt.FlowLayout; import java.io.File; import java.io.IOException; import java.util.HashMap; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.knime.core.data.DataTableSpec; import au.com.acpfg.misc.jemboss.local.JEmbossProcessorNodeModel; import au.com.acpfg.misc.jemboss.local.ProgramSettingsListener; /** * Output files produced by emboss programs eg. featout are handled by this setting. * An output file, unlike a datafile setting, has three modes of operation: * 1) concatenation of each result to a single file (as specified by the user) * 2) discard the result file * 3) output to a column in the KNIME table, using a cell type appropriate to the data * This class uses the superclass(es) where it can and overrides the rest. * * @author andrew.cassin * */ public class OutputFileSetting extends DataFileSetting { private File m_file; // NB: this is NOT persisted, but calculated when executing private boolean m_to_file, m_to_discard, m_to_col; public OutputFileSetting(HashMap<String,String> attrs) { super(attrs); // for output files, we dont want the default folder to be an EMBOSS directory, // so override that try { File tmp_file = File.createTempFile("prefix", "suffix"); setFolder(tmp_file.getParentFile()); tmp_file.delete(); } catch (IOException ioe) { ioe.printStackTrace(); } } @Override public JComponent make_widget(DataTableSpec dt) { JComponent file_selector = super.make_widget(dt); JPanel ret = new JPanel(); ret.setLayout(new FlowLayout()); JPanel file_panel = new JPanel(); file_panel.setLayout(new FlowLayout()); final JRadioButton rb_file = new JRadioButton("to file"); final JRadioButton rb_discard = new JRadioButton("discard output"); final JRadioButton rb_col = new JRadioButton("to column"); ChangeListener cl = new ChangeListener() { @Override public void stateChanged(ChangeEvent src) { if (src.getSource().equals(rb_file)) { rb_file.setSelected(true); rb_discard.setSelected(false); rb_col.setSelected(false); } else if (src.getSource().equals(rb_discard)) { rb_file.setSelected(false); rb_discard.setSelected(true); rb_col.setSelected(false); } else { // must be rb_col rb_file.setSelected(false); rb_discard.setSelected(false); rb_col.setSelected(true); } m_to_file = rb_file.isSelected(); m_to_discard = rb_discard.isSelected(); m_to_col = rb_col.isSelected(); } }; rb_file.addChangeListener(cl); rb_discard.addChangeListener(cl); rb_col.addChangeListener(cl); file_panel.add(rb_file); file_panel.add(file_selector); ret.add(file_panel); ret.add(rb_discard); ret.add(rb_col); return ret; } @Override public void getArguments(ProgramSettingsListener l) throws IOException { m_file = null; // cpgplot is very fussy about the -outfeat argument, so we cater to some of its whims here... if (getType().equals("featout")) { m_file = File.createTempFile("output-features", ".gff3", JEmbossProcessorNodeModel.get_tmp_folder()); } else if (getType().indexOf("seq") >= 0) { // HACK BUG: the only sequence format currently supported is FASTA m_file = File.createTempFile(getType(), ".fasta"); } else { m_file = File.createTempFile("jemboss-node", "."+getName()+"out"); } l.addOutputFileArgument(this, "-"+getName()); } public static boolean canEmboss(String acd_type) { if (acd_type.equals("featout") || acd_type.equals("outfile") || acd_type.equals("report")) return true; return false; } /** * Returns true if the file specified by the setting for output does not exist at this time * or it exists but has no data. Subclasses are free to override. * BUG: this code has an inherent race condition given the time between being invoked and * the time the io operation takes place. * * @return <code>true</code> if the file is safe to delete, <code>false</code> otherwise */ public boolean isSafeToDelete() { assert(m_file != null); if (m_file.exists() && m_file.length() > 0) { return false; } return true; } /** * This method should only be called when building an emboss command line and returns the * <code>java.io.File</code> instance which represents the output file * @return */ public File getFile() { assert(m_file != null); return m_file; } /** * Returns the filename appropriate for the setting. Some programs require * an absolute path, others just the name and this method tailors the name based on * the program being invoked */ @Override public String getFileName() { if (getType().equals("featout")) { return m_file.getName(); } return m_file.getAbsolutePath(); } }