Skip to content
Snippets Groups Projects
EntryFileDialog.java 19.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • tjc's avatar
    tjc committed
    /* EntryFileDialog.java
     *
     * created: Mon Dec  7 1998
     *
     * This file is part of Artemis
     *
     * Copyright(C) 1998-2003  Genome Research Limited
     *
     * 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 2
     * 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, write to the Free Software
     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     *
    
     * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/EntryFileDialog.java,v 1.15 2009-04-01 12:23:20 tjc Exp $
    
    tjc's avatar
    tjc committed
     */
    
    package uk.ac.sanger.artemis.components;
    
    import uk.ac.sanger.artemis.Options;
    import uk.ac.sanger.artemis.util.*;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.DatabaseDocumentEntry;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.Entry;
    import uk.ac.sanger.artemis.io.DocumentEntryFactory;
    
    import uk.ac.sanger.artemis.io.GFFDocumentEntry;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.ReadFormatException;
    import uk.ac.sanger.artemis.io.EntryInformation;
    import uk.ac.sanger.artemis.io.EntryInformationException;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.DocumentEntry;
    
    import uk.ac.sanger.artemis.io.ReadAndWriteEntry;
    
    tjc's avatar
    tjc committed
    
    
    import java.io.*;
    
    tjc's avatar
    tjc committed
    import javax.swing.*;
    
    /**
     *  This class is a JFileChooser that can read EMBL Entry objects.
     *
     *  @author Kim Rutherford
    
     *  @version $Id: EntryFileDialog.java,v 1.15 2009-04-01 12:23:20 tjc Exp $
    
    tjc's avatar
    tjc committed
     **/
    
    public class EntryFileDialog extends StickyFileChooser 
    {
    
    
    tjc's avatar
    tjc committed
      /** */
      private static final long serialVersionUID = 1L;
    
    tjc's avatar
    tjc committed
      /** JFrame reference that was passed to the constructor. */
      private JFrame owner = null;
    
      /**
       *  Create a new EntryFileDialog component.
       *  @param owner The component where this dialog was created.
       *  @param sequence_only If true default to showing only file that have
       *    suffixes that suggest that the files contain sequence(eg. .embl,
       *    .seq, .dna).  Of false show all files that can be read.
       **/
      public EntryFileDialog(final JFrame owner,
                             final boolean show_sequence_only) 
      {
        super();
        this.owner = owner;
    
        setFileSelectionMode(JFileChooser.FILES_ONLY);
        setMultiSelectionEnabled(false);
    
        final StringVector sequence_suffixes =
          Options.getOptions().getOptionValues("sequence_file_suffixes");
    
        final StringVector feature_suffixes =
          Options.getOptions().getOptionValues("feature_file_suffixes");
    
        final javax.swing.filechooser.FileFilter artemis_filter =
          new javax.swing.filechooser.FileFilter()
        {
            public boolean accept(final File file) 
            {
              if(file.isDirectory()) 
                return true;
    
              for(int i = 0; i<sequence_suffixes.size(); ++i) 
              {
    
    tjc's avatar
    tjc committed
                final String this_suffix = (String)sequence_suffixes.elementAt(i);
    
    tjc's avatar
    tjc committed
    
                if(file.getName().endsWith("." + this_suffix) ||
                    file.getName().endsWith("." + this_suffix + ".gz")) 
                  return true;
              }
    
              for(int i = 0; i<feature_suffixes.size(); ++i) 
              {
    
    tjc's avatar
    tjc committed
                final String this_suffix = (String)feature_suffixes.elementAt(i);
    
    tjc's avatar
    tjc committed
    
                if(file.getName().endsWith("." + this_suffix) ||
                   file.getName().endsWith("." + this_suffix + ".gz")) 
                  return true;
              }
              return false;
            }
    
            public String getDescription() 
            {
              return "Artemis files";
            }
          };
    
        final javax.swing.filechooser.FileFilter feature_filter =
          new javax.swing.filechooser.FileFilter() 
        {
            public boolean accept(final File file) 
            {
              if(file.isDirectory()) 
                return true;
    
              for(int i = 0 ; i < feature_suffixes.size() ; ++i) 
              {
    
    tjc's avatar
    tjc committed
                final String this_suffix = (String)feature_suffixes.elementAt(i);
    
    tjc's avatar
    tjc committed
    
                if(file.getName().endsWith("." + this_suffix) ||
                   file.getName().endsWith("." + this_suffix + ".gz")) 
                  return true;
              }
    
              return false;
            }
    
            public String getDescription() 
            {
              return "Feature files";
            }
          };
    
        final javax.swing.filechooser.FileFilter sequence_filter =
          new javax.swing.filechooser.FileFilter() 
          {
            public boolean accept(final File file) 
            {
              if(file.isDirectory()) 
                return true;
    
              for(int i = 0 ; i<sequence_suffixes.size() ; ++i) 
              {
    
    tjc's avatar
    tjc committed
                final String this_suffix = (String)sequence_suffixes.elementAt(i);
    
    tjc's avatar
    tjc committed
    
                if(file.getName().endsWith("." + this_suffix) ||
                   file.getName().endsWith("." + this_suffix + ".gz")) 
                  return true;
              }
    
              return false;
            }
    
            public String getDescription() 
            {
              return "Sequence files";
            }
          };
    
        addChoosableFileFilter(artemis_filter);
        addChoosableFileFilter(feature_filter);
        addChoosableFileFilter(sequence_filter); 
    
        if(show_sequence_only) 
          setFileFilter(sequence_filter);
        else 
          setFileFilter(artemis_filter);
      }
    
      /**
       *  Return an uk.ac.sanger.artemis.io.Entry object representing the file
       *  the user has selected with the dialog or null if the read failed for any
       *  reason.
       *  @param entry_information The EntryInformation to use when reading.  This
       *    supplies the list of valid keys and qualifiers.  If a key or qualifier
       *    is read that is incompatible with this EntryInformation object the
       *    EntryInformation will be changed to cope.
       *  @param listener The object to which InputStreamProgressEvents will be
       *    send while reading.
       *  @exception EntryInformationException Thrown if an Entry using the given
       *    EntryInformation object cannot contain the Key, Qualifier or
       *    Key/Qualifier combination of one of the features in the Document.
       *  @param show_progress If true a InputStreamProgressDialog will be shown
       *    while loading.
       **/
      public Entry getEntry(final EntryInformation entry_information,
                            final InputStreamProgressListener listener,
                            final boolean show_progress) 
      {
        setDialogTitle("Select a file ...");
        setDialogType(JFileChooser.OPEN_DIALOG);
        SecurityManager sm = System.getSecurityManager();
        System.setSecurityManager(null);
    
        final int status = showOpenDialog(owner);
    
        System.setSecurityManager(sm);
    
        if(status != JFileChooser.APPROVE_OPTION ||
           getSelectedFile() == null) 
          return null;
    
        final File file = new File(getCurrentDirectory(),
                                   getSelectedFile().getName());
    
        return getEntryFromFile(owner, new FileDocument(file),
                                entry_information, show_progress); 
      }
    
      /**
       *  This exists only to get around a bug in the 1.1/1.2 code generator,
       *  which generates unverifiable code.
       *  @param frame Used when creating MessageDialog components.
       *  @param file_document The Document to read the Entry from(should be made
       *    from entry_file).
       *  @param entry_information The EntryInformation to use when reading.  This
       *    supplies the list of valid keys and qualifiers.  If a key or qualifier
       *    is read that is incompatible with this EntryInformation object the
       *    EntryInformation will be changed to cope.
       **/
      private static Entry getEntryFromFileHelper(final JFrame frame,
                                final Document file_document,
                                final EntryInformation entry_information)
          throws ReadFormatException, IOException 
      {
    
        final LogReadListener read_event_logger =
          new LogReadListener(file_document.getName());
    
        final Entry new_entry;
    
        try 
        {
          new_entry =
            DocumentEntryFactory.makeDocumentEntry(entry_information,
                                     file_document,read_event_logger);
        }
        catch(EntryInformationException e) 
        {
          throw new Error("internal error - unexpected exception: " + e);
        }
    
    
    tjc's avatar
    tjc committed
        if(read_event_logger.seenMessage() && !Options.isBlackBeltMode())
    
    tjc's avatar
    tjc committed
        {
          final YesNoDialog yes_no_dialog = new YesNoDialog(frame,
                             "there were warnings while reading - view now?");
    
          if(yes_no_dialog.getResult()) 
            Splash.showLog();
        }
    
        return new_entry;
      }
    
      /**
       *  Read and return an Entry from the given File.
       *  @param frame Used when creating MessageDialog components.
       *  @param entry_file The file to read the Entry from.
       *  @param entry_information The EntryInformation to use when reading.  This
       *    supplies the list of valid keys and qualifiers.  If a key or qualifier
       *    is read that is incompatible with this EntryInformation object the
       *    EntryInformation will be changed to cope.
       *  @param listener The object to which InputStreamProgressEvents will be
       *    send while reading.
       *  @param show_progress If true a InputStreamProgressDialog will be shown
       *    while loading.
       **/
      public static Entry getEntryFromFile(final JFrame frame,
                         final Document entry_document,
                         final EntryInformation entry_information,
                         final boolean show_progress) 
      {
        InputStreamProgressDialog progress_dialog = null;
    
    
        if(show_progress) 
        {
    
    tjc's avatar
    tjc committed
    // XXX FIXME
    
    // This doesn't work because getEntryFromFile() is called from the Swing
    // thread so the Dialog never gets updated
    
    
           progress_dialog =
             new InputStreamProgressDialog(frame, "Reading ...",
                                            "Reading from " +
                                            entry_document.getName(), false);
           final InputStreamProgressListener listener =
             progress_dialog.getInputStreamProgressListener();
    
    tjc's avatar
    tjc committed
    
    
           entry_document.addInputStreamProgressListener(listener);
    
    tjc's avatar
    tjc committed
        }
    
        try 
        {
          return getEntryFromFileHelper(frame, entry_document,
                                        entry_information);
        }
        catch(ReadFormatException e) 
        {
          final String message =
            "failed to open " + entry_document.getName() + ": " +
            e.getMessage() +(e.getLineNumber() > 1 ?
                               " at line: " + e.getLineNumber() :
                               "");
          System.out.println(message);
          new MessageDialog(frame, message);
        }
        catch(FileNotFoundException e) 
        {
          final String message =
            "failed to open " + entry_document.getName() + ": file not found";
          new MessageDialog(frame, message);
        }
        catch(IOException e) 
        {
          final String message =
            "failed to open " + entry_document.getName() + ": " + e.getMessage();
          new MessageDialog(frame, message);
        }
        finally
        {
    
          if(progress_dialog != null) 
            progress_dialog.dispose();
    
    tjc's avatar
    tjc committed
        }
        return null;
      }
    
      /**
       *  Save the given entry, prompting for a file name if necessary.
       *  @param include_diana_extensions If true then the any diana additions to
       *    the embl file format will be included in the output, otherwise they
       *    will be removed.  Also possible problems that would cause an entry to
       *    bounce from the EMBL submission process will be flagged if this is
       *    true.
       *  @param ask_for_name If true then always prompt for a new filename,
       *    otherwise prompt only when the entry name is not set.
       *  @param keep_new_name If ask_for_name is true a file will be written with
       *    the new name the user selects - if keep_new_name is true as well, then
       *    the entry will have it's name set to the new name, otherwise it will
       *    be used for this save and then discarded.
       *  @param destination_type Should be one of EMBL_FORMAT, GENBANK_FORMAT or
       *    ANY_FORMAT.  If ANY_FORMAT then the Entry will be saved in the
       *    same format it was created, otherwise it will be saved in the given
       *    format.
       **/
      void saveEntry(final uk.ac.sanger.artemis.Entry entry,
                      final boolean include_diana_extensions,
                      final boolean ask_for_name,
                      final boolean keep_new_name,
                      final int destination_type) 
      {
    
    tjc's avatar
    tjc committed
    
        JCheckBox remoteSave = new JCheckBox("Ssh/Remote Save",
                                             true);
        File file = null;
    
    
    tjc's avatar
    tjc committed
        try 
        {
          if(ask_for_name || entry.getName() == null) 
          {
    
    tjc's avatar
    tjc committed
            Box yBox = Box.createVerticalBox();
            boolean useAccessory = false;
    
    
    tjc's avatar
    tjc committed
            JCheckBox emblHeader = new JCheckBox("Add EMBL Header",
                                                 false);
    
    tjc's avatar
    tjc committed
            setDialogTitle("Save to ...");
            setDialogType(JFileChooser.SAVE_DIALOG);
    
    
            if( destination_type == DocumentEntryFactory.EMBL_FORMAT &&
               (entry.getHeaderText() == null ||
               !isHeaderEMBL(entry.getHeaderText())) )
    
    tjc's avatar
    tjc committed
            {
              yBox.add(emblHeader);
              useAccessory = true;
            }
    
    
    tjc's avatar
    tjc committed
            final JCheckBox flattenGeneModel = new JCheckBox("Flatten Gene Model",
    
    tjc's avatar
    tjc committed
            final JCheckBox ignoreObsoleteFeatures = new JCheckBox(
                                  "Ignore obsolete features", true);
    
    tjc's avatar
    tjc committed
            if(((DocumentEntry)entry.getEMBLEntry()).getDocument() 
                                           instanceof RemoteFileDocument)
            {
              yBox.add(remoteSave);
              useAccessory = true;
            }
    
            else if(entry.getEMBLEntry() instanceof DatabaseDocumentEntry ||
                    entry.getEMBLEntry() instanceof GFFDocumentEntry)
    
    tjc's avatar
    tjc committed
            {
              yBox.add(flattenGeneModel);
    
              if(entry.getEMBLEntry() instanceof DatabaseDocumentEntry)
                yBox.add(ignoreObsoleteFeatures);
    
    tjc's avatar
    tjc committed
              useAccessory = true;
            }
    
    tjc's avatar
    tjc committed
    
            if(useAccessory)
              setAccessory(yBox);
    
    
    tcarver's avatar
    tcarver committed
            switch(destination_type) // provide a suffix
            {
              case DocumentEntryFactory.EMBL_FORMAT:
                super.setSelectedFile(new File(".embl"));
    
                flattenGeneModel.setSelected(true);
    
    tcarver's avatar
    tcarver committed
                break;
              case DocumentEntryFactory.GENBANK_FORMAT:
                super.setSelectedFile(new File(".gbk"));
    
                flattenGeneModel.setSelected(true);
    
    tcarver's avatar
    tcarver committed
                break;
              case DocumentEntryFactory.GFF_FORMAT:
                super.setSelectedFile(new File(".gff"));
                break;
              default:
                break;
            }
    
    tjc's avatar
    tjc committed
            int status = showSaveDialog(owner);
    
            if(status != JFileChooser.APPROVE_OPTION ||
               getSelectedFile() == null) 
              return;
    
    
            if(emblHeader.isSelected())
            {
              Box bdown = Box.createVerticalBox();
              JTextField idField = new JTextField("");
              bdown.add(idField);
    
              int n = JOptionPane.showConfirmDialog(null, bdown,
                                "Enter the entry ID",
                                JOptionPane.OK_CANCEL_OPTION,
                                JOptionPane.QUESTION_MESSAGE);
    
              if(n != JOptionPane.CANCEL_OPTION &&
                 !idField.getText().trim().equals(""))
              {
    
    tjc's avatar
    tjc committed
                int length = entry.getBases().getLength();
                String header = "ID   "+idField.getText().trim()+"; SV ; ; ; ; ; "+length+" BP.";
                //String header = "ID   "+idField.getText().trim();
    
                if(entry.getFeatureCount() > 0)
                  header = header.concat("\nFH   Key             "+
                                         "Location/Qualifiers\nFH\n");
                entry.setHeaderText(header);
              }
            }
    
    
    tjc's avatar
    tjc committed
            file = new File(getCurrentDirectory(),
    
    tjc's avatar
    tjc committed
                            getSelectedFile().getName());
    
            if(file.exists()) 
            {
              final YesNoDialog yes_no_dialog = new YesNoDialog(owner,
                               "this file exists: " + file.getName() +
                               " overwrite it?");
    
              if(!yes_no_dialog.getResult()) 
                return;
            }
    
            final MessageDialog message = new MessageDialog(owner,
                                 "saving to " + file.getName() + " ...",
                                 false);
            try 
            {
    
              if(entry.getEMBLEntry() instanceof DatabaseDocumentEntry ||
                 entry.getEMBLEntry() instanceof GFFDocumentEntry)
    
    tjc's avatar
    tjc committed
                ReadAndWriteEntry.writeDatabaseEntryToFile(entry, file, 
    
    tjc's avatar
    tjc committed
                    flattenGeneModel.isSelected(), 
    
                    ignoreObsoleteFeatures.isSelected(), false, 
    
                    include_diana_extensions, false, destination_type, owner);
    
    tjc's avatar
    tjc committed
              else if(include_diana_extensions) 
    
    tjc's avatar
    tjc committed
                entry.save(file, destination_type, false);
              else 
                entry.saveStandardOnly(file, destination_type, true);
            }
            catch(EntryInformationException e) 
            {
              final YesNoDialog yes_no_dialog = new YesNoDialog(owner,
                                 "destination format can't handle all " +
                                 "keys/qualifiers - continue?");
    
    tjc's avatar
    tjc committed
              
    
    tjc's avatar
    tjc committed
              if(yes_no_dialog.getResult()) 
              {
                try 
                {
    
    tjc's avatar
    tjc committed
                  if(entry.getEMBLEntry() instanceof DatabaseDocumentEntry)
    
    tjc's avatar
    tjc committed
                    ReadAndWriteEntry.writeDatabaseEntryToFile(entry, file, 
    
    tjc's avatar
    tjc committed
                        flattenGeneModel.isSelected(), 
    
                        ignoreObsoleteFeatures.isSelected(), true, 
    
                        include_diana_extensions, false, destination_type, null);
    
    tjc's avatar
    tjc committed
                  else if(include_diana_extensions) 
    
    tjc's avatar
    tjc committed
                    entry.save(file, destination_type, true);
                  else 
                    entry.saveStandardOnly(file, destination_type, true);
                }
                catch(EntryInformationException e2) 
                {
                  throw new Error("internal error - unexpected exception: "+ e);
                }
              } 
              else 
                return;
            }
            finally 
            {
              if(message != null) 
                message.dispose();
            }
    
            if(keep_new_name) 
              entry.setName(file.getName());
          }
          else 
          {
            final MessageDialog message = new MessageDialog(owner,
                                 "saving to " + entry.getName() + " ...",
                                 false);
            try 
            {
              if(include_diana_extensions) 
                entry.save(destination_type);
              else 
                entry.saveStandardOnly(destination_type);
            }
            finally 
            {
              message.dispose();
            }
          }
        } 
        catch(ReadOnlyException e) 
        {
          new MessageDialog(owner, "this entry is read only");
          return;
        }
        catch(IOException e) 
        {
          new MessageDialog(owner, "error while saving: " + e);
          return;
        } 
        catch(EntryInformationException e) 
        {
          new MessageDialog(owner, "error while saving: " + e);
          return;
        }
    
    tjc's avatar
    tjc committed
    
        // save it back to ssh server
        if(((DocumentEntry)entry.getEMBLEntry()).getDocument()
                                       instanceof RemoteFileDocument &&
            remoteSave.isSelected())
        {
           RemoteFileDocument node =
               (RemoteFileDocument)(((DocumentEntry)entry.getEMBLEntry()).getDocument());
    
           if(file == null)
    
    tjc's avatar
    tjc committed
             file = new File( ((DocumentEntry)entry.getEMBLEntry()).getDocument().getLocation().toString() );
    
    tjc's avatar
    tjc committed
           node.saveEntry(file);
        }
    
    
    tjc's avatar
    tjc committed
      }
    
    
      /**
      *
      * Test for that the header of an EMBL entry begins
      * with an ID line.
      * @param header embl header
      *
      */
      private boolean isHeaderEMBL(String header)
      {
        StringReader reader = new StringReader(header);
        BufferedReader buff_reader = new BufferedReader(reader);
    
        try
        {  
          if(!buff_reader.readLine().startsWith("ID"))
            return false;
        }
        catch(IOException ioe){}
        return true;
      }
    
    
    
    tjc's avatar
    tjc committed
    }