Skip to content
Snippets Groups Projects
DatabaseJPanel.java 16.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • tjc's avatar
    tjc committed
    /* DatabaseJPanel.java
    
     *
     * created: June 2005
     *
     * This file is part of Artemis
     *
    
    tjc's avatar
    tjc committed
     * Copyright(C) 2005,2006  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.
     *
    
    tjc's avatar
    tjc committed
     * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/database/DatabaseJPanel.java,v 1.16 2008-10-10 14:45:35 tjc Exp $
    
    package uk.ac.sanger.artemis.components.database;
    
    import uk.ac.sanger.artemis.components.*;
    
    
    import uk.ac.sanger.artemis.Entry;
    import uk.ac.sanger.artemis.sequence.*;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.util.InputStreamProgressEvent;
    
    import uk.ac.sanger.artemis.util.InputStreamProgressListener;
    import uk.ac.sanger.artemis.util.OutOfRangeException;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.util.DatabaseDocument;
    import uk.ac.sanger.artemis.io.DatabaseDocumentEntry;
    
    import uk.ac.sanger.artemis.io.Range;
    
    tjc's avatar
    tjc committed
    import javax.swing.JComponent;
    
    import javax.swing.JTree;
    import javax.swing.JScrollPane;
    
    import javax.swing.JSeparator;
    import javax.swing.JMenuBar;
    import javax.swing.JMenu;
    import javax.swing.JMenuItem;
    
    tjc's avatar
    tjc committed
    import javax.swing.JCheckBoxMenuItem;
    
    tjc's avatar
    tjc committed
    import javax.swing.JPanel;
    import javax.swing.JLabel;
    import javax.swing.BorderFactory;
    import javax.swing.border.Border;
    
    import javax.swing.tree.TreePath;
    
    
    tjc's avatar
    tjc committed
    import org.gmod.schema.sequence.Feature;
    
    tjc's avatar
    tjc committed
    import java.awt.BorderLayout;
    
    import java.awt.event.ActionListener;
    import java.awt.event.ActionEvent;
    
    import java.awt.event.MouseListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.Dimension;
    import java.awt.Toolkit;
    import java.awt.Cursor;
    
    tjc's avatar
    tjc committed
    import java.awt.FontMetrics;
    
    import java.io.*;
    
    import java.net.ConnectException;
    import java.sql.SQLException;
    import java.util.Arrays;
    
    tjc's avatar
    tjc committed
    import java.util.Comparator;
    
    tjc's avatar
    tjc committed
    import java.util.HashMap;
    
    import java.util.List;
    
    tjc's avatar
    tjc committed
    import java.util.Vector;
    
    tjc's avatar
    tjc committed
    public class DatabaseJPanel extends JPanel
    
    tjc's avatar
    tjc committed
      /** */
      private static final long serialVersionUID = 1L;
    
    tjc's avatar
    tjc committed
      private JLabel status_line = new JLabel("");
    
    tjc's avatar
    tjc committed
      private boolean splitGFFEntry = false;
    
    tjc's avatar
    tjc committed
      private JTree tree;
    
    tjc's avatar
    tjc committed
      private DatabaseDocument doc;
    
    tjc's avatar
    tjc committed
      private static org.apache.log4j.Logger logger4j = 
        org.apache.log4j.Logger.getLogger(DatabaseJPanel.class);
    
    tjc's avatar
    tjc committed
      
      public DatabaseJPanel(final DatabaseEntrySource entry_source,
                            final Splash splash_main)
    
    tjc's avatar
    tjc committed
        setLayout(new BorderLayout());
    
        tree = getDatabaseTree(entry_source);
    
    tjc's avatar
    tjc committed
        // Listen for when the selection changes.
    
        MouseListener mouseListener = new MouseAdapter()
        {
          public void mouseClicked(MouseEvent e)
          {
    
            if(e.getClickCount() == 2 && !e.isPopupTrigger())
    
              showSelected(entry_source, tree, splash_main);
    
          }
        };
        tree.addMouseListener(mouseListener);
    
        JScrollPane scroll = new JScrollPane(tree);
    
        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
    
    tjc's avatar
    tjc committed
        Dimension dim_frame = new Dimension(screen.width * 2 / 10,
                                            screen.height * 6 / 10);
    
        scroll.setPreferredSize(dim_frame);
    
    
    tjc's avatar
    tjc committed
        add(scroll, BorderLayout.CENTER);
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        final FontMetrics fm = this.getFontMetrics(status_line.getFont());
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        final int font_height = fm.getHeight() + 10;
    
    tjc's avatar
    tjc committed
        status_line.setMinimumSize(new Dimension(100, font_height));
        status_line.setPreferredSize(new Dimension(100, font_height));
    
        Border loweredbevel = BorderFactory.createLoweredBevelBorder();
        Border raisedbevel = BorderFactory.createRaisedBevelBorder();
    
    tjc's avatar
    tjc committed
        Border compound = BorderFactory.createCompoundBorder(raisedbevel,
                                                             loweredbevel);
    
    tjc's avatar
    tjc committed
        status_line.setBorder(compound);
    
    tjc's avatar
    tjc committed
        add(status_line, BorderLayout.SOUTH);
        
        JLabel title_line = new JLabel("Database List");
        title_line.setMinimumSize(new Dimension(100, font_height));
        title_line.setPreferredSize(new Dimension(100, font_height));
        title_line.setBorder(compound);
        add(title_line, BorderLayout.NORTH);
    
    tjc's avatar
    tjc committed
       * Show the selected sequence in the tree
    
    tjc's avatar
    tjc committed
       * @param entry_source
       * @param tree
       * @param splash_main
    
    tjc's avatar
    tjc committed
       */
    
      private void showSelected(final DatabaseEntrySource entry_source,
    
          final JTree tree, final Splash splash_main)
    
          TreePath path = tree.getLeadSelectionPath();
          if(path == null)
            return;
          DatabaseTreeNode seq_node = 
            (DatabaseTreeNode)path.getLastPathComponent();
          String node_name = (String)seq_node.getUserObject();
    
    tjc's avatar
    tjc committed
          String userName;
          if(!doc.isSingleSchema())
            userName = seq_node.getSchema();
          else
            userName = doc.getUserName();
    
    
          String id = seq_node.getFeatureId(); 
    
    tjc's avatar
    tjc committed
            getEntryEditFromDatabase(id, entry_source, tree, 
                status_line, stream_progress_listener, 
                splitGFFEntry, splash_main, 
    
    tjc's avatar
    tjc committed
                node_name, userName);
    
    tjc's avatar
    tjc committed
        catch(NullPointerException npe)
        {
        }
    
    tjc's avatar
    tjc committed
      
      /**
       * Open an Artemis EntryEdit window
       * @param entry_source
       * @param splash_main
       * @param stream_progress_listener
    
       * @param entryName                 e.g. Pfalciparum:Pf3D7_09 or 
       *                                  Pfalciparum:Pf3D7_09:20050..40000
    
    tjc's avatar
    tjc committed
       * @return
       */
      public static EntryEdit show(final DatabaseEntrySource entry_source,
                              final Splash splash_main,
                              final InputStreamProgressListener stream_progress_listener,
                              final String entryName)
      {
        final String entry[] = entryName.split(":");
        String url = (String)entry_source.getLocation();
        int index  = url.indexOf("?");
        
        String userName = url.substring(index+1).trim();
        if(userName.startsWith("user="))
          userName = userName.substring(5);
        
        DatabaseDocument doc = entry_source.getDatabaseDocument();
    
        
        Range range = null;
        if(entry.length>2)
        {
          if(entry[2].indexOf("..") > -1)
          {
            String ranges[] = entry[2].split("\\.\\.");
            if(ranges.length == 2)
            {
              try
              {
                range = new Range(Integer.parseInt(ranges[0]), 
                                  Integer.parseInt(ranges[1]));
              }
              catch(Exception e){ e.printStackTrace(); }
            }
          }
        }
        
    
    tjc's avatar
    tjc committed
        Feature f = doc.getFeatureByUniquename(entry[1]);
        
        return openEntry(Integer.toString(f.getFeatureId()), entry_source, 
            splash_main.getCanvas(), splash_main.getStatusLabel(), stream_progress_listener,
    
            false, splash_main,  entry[1], userName, range);
    
    tjc's avatar
    tjc committed
      }
    
    tjc's avatar
    tjc committed
       * Retrieve a database entry.
    
    tjc's avatar
    tjc committed
       * @param srcfeatureId
    
    tjc's avatar
    tjc committed
       * @param entry_source
    
    tjc's avatar
    tjc committed
       * @param srcComponent
       * @param status_line
       * @param stream_progress_listener
       * @param splitGFFEntry
    
    tjc's avatar
    tjc committed
       * @param splash_main
    
    tjc's avatar
    tjc committed
       * @param dbDocumentName
    
    tjc's avatar
    tjc committed
       * @param userName
    
    tjc's avatar
    tjc committed
       */
    
    tjc's avatar
    tjc committed
      private static void getEntryEditFromDatabase(
          final String srcfeatureId,
          final DatabaseEntrySource entry_source, 
          final JComponent srcComponent,
          final JLabel status_line,
          final InputStreamProgressListener stream_progress_listener,
          final boolean splitGFFEntry,
          final Splash splash_main, 
          final String dbDocumentName,
    
    tjc's avatar
    tjc committed
          final String userName)
    
      {
        SwingWorker entryWorker = new SwingWorker()
        {
          public Object construct()
          {
    
    tjc's avatar
    tjc committed
            Cursor cbusy = new Cursor(Cursor.WAIT_CURSOR);
            Cursor cdone = new Cursor(Cursor.DEFAULT_CURSOR);
    
            status_line.setText("Retrieving sequence....");
    
    tjc's avatar
    tjc committed
            srcComponent.setCursor(cbusy);
    
    tjc's avatar
    tjc committed
              openEntry(srcfeatureId, entry_source, srcComponent, status_line, stream_progress_listener,
    
                  splitGFFEntry, splash_main, dbDocumentName, userName, null);
    
    tjc's avatar
    tjc committed
            catch(RuntimeException re)
    
    tjc's avatar
    tjc committed
              logger4j.warn(re.getMessage());
              final DatabaseEntrySource entry_source = new DatabaseEntrySource();
    
    tjc's avatar
    tjc committed
              entry_source.setLocation(true);
    
              String url = entry_source.getLocation();
              int index  = url.indexOf("?");
                
              String userName = url.substring(index+1).trim();
              if(userName.startsWith("user="))
                userName = userName.substring(5);
                
              openEntry(srcfeatureId, entry_source, srcComponent, status_line, stream_progress_listener,
    
                  splitGFFEntry, splash_main, dbDocumentName, userName, null);
    
    tjc's avatar
    tjc committed
            srcComponent.setCursor(cdone);
    
      /**
       * 
       * @param srcfeatureId
       * @param entry_source
       * @param srcComponent
       * @param status_line
       * @param stream_progress_listener
       * @param splitGFFEntry
       * @param splash_main
       * @param dbDocumentName
       * @param userName
       * @param range           range for to retrieve features in
       * @return
       */
    
    tjc's avatar
    tjc committed
      private static EntryEdit openEntry(
    
    tjc's avatar
    tjc committed
          final String srcfeatureId,
          final DatabaseEntrySource entry_source, 
          final JComponent srcComponent,
          final JLabel status_line,
          final InputStreamProgressListener stream_progress_listener,
          final boolean splitGFFEntry,
          final Splash splash_main, 
          final String dbDocumentName,
    
          final String userName,
          final Range range) 
    
    tjc's avatar
    tjc committed
      {
        Cursor cdone = new Cursor(Cursor.DEFAULT_CURSOR);
        try
        {
    
          if(range != null)
            logger4j.info("LOAD FEATURES IN THE RANGE : "+range.toString());
    
    tjc's avatar
    tjc committed
          entry_source.setSplitGFF(splitGFFEntry);
    
          final Entry entry = entry_source.getEntry(srcfeatureId, userName,
    
              stream_progress_listener, range);
    
    tjc's avatar
    tjc committed
    
          DatabaseDocumentEntry db_entry = (DatabaseDocumentEntry) entry
              .getEMBLEntry();
          DatabaseDocument doc = (DatabaseDocument) db_entry.getDocument();
          doc.setName(dbDocumentName);
    
          if(entry == null)
          {
            srcComponent.setCursor(cdone);
            status_line.setText("No entry.");
    
    tjc's avatar
    tjc committed
            return null;
    
    tjc's avatar
    tjc committed
          }
    
          final EntryEdit new_entry_edit = ArtemisMain.makeEntryEdit(entry);
    
          // add gff entries
          if(splitGFFEntry)
          {
            final DatabaseDocumentEntry[] entries = entry_source.makeFromGff(
                (DatabaseDocument) db_entry.getDocument(), srcfeatureId, userName);
            for(int i = 0; i < entries.length; i++)
            {
              if(entries[i] == null)
                continue;
    
              final Entry new_entry = new Entry(new_entry_edit.getEntryGroup()
                  .getBases(), entries[i]);
              new_entry_edit.getEntryGroup().add(new_entry);
            }
          }
    
          new_entry_edit.setVisible(true);
          status_line.setText("Sequence loaded.");
    
    tjc's avatar
    tjc committed
          return new_entry_edit;
    
    tjc's avatar
    tjc committed
        }
        catch(OutOfRangeException e)
        {
          new MessageDialog(splash_main, "read failed: one of the features in "
              + " the entry has an out of range " + "location: "
              + e.getMessage());
        }
        catch(NoSequenceException e)
        {
          new MessageDialog(splash_main, "read failed: entry contains no sequence");
        }
        catch(IOException e)
        {
          new MessageDialog(splash_main, "read failed due to IO error: " + e);
        }
    
    tjc's avatar
    tjc committed
        return null;
    
    tjc's avatar
    tjc committed
      }
    
    
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
      /**
       * Create a menu bar 
       * @param entry_source
       * @param splash_main
       * @return
       */
      public JMenuBar makeMenuBar(final DatabaseEntrySource entry_source,
                                  final Splash splash_main)
    
      {
        JMenuBar mBar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        mBar.add(fileMenu);
    
        JMenuItem fileShow = new JMenuItem("Open Selected Sequence ...");
        fileShow.addActionListener(new ActionListener()
        {
          public void actionPerformed(ActionEvent e)
          {
    
            showSelected(entry_source, tree, splash_main);
    
          }
        });
        fileMenu.add(fileShow);
        fileMenu.add(new JSeparator());
    
        JMenuItem fileMenuClose = new JMenuItem("Close");
        fileMenuClose.addActionListener(new ActionListener()
        {
          public void actionPerformed(ActionEvent e)
          {
            setVisible(false);
          }
        });
        fileMenu.add(fileMenuClose);
    
    
    tjc's avatar
    tjc committed
        JMenu optionMenu = new JMenu("Options");
        mBar.add(optionMenu);
    
    
    tjc's avatar
    tjc committed
        final JCheckBoxMenuItem splitGFF = new JCheckBoxMenuItem(
                        "Split GFF into entries", splitGFFEntry);
    
    tjc's avatar
    tjc committed
        splitGFF.addActionListener(new ActionListener()
        {
          public void actionPerformed(ActionEvent e)
          {
            if(splitGFF.isSelected())
              splitGFFEntry = true;
            else
              splitGFFEntry = false;
          }
        });
        optionMenu.add(splitGFF);
    
    
      /**
       * Create database organism JTree.
       */
      private JTree getDatabaseTree(final DatabaseEntrySource entry_source)
      {
    
    tjc's avatar
    tjc committed
        HashMap entries = null;
    
        
        while(entries == null)
        {
          try
          {
    
    tjc's avatar
    tjc committed
            doc = entry_source.getDatabaseDocument();
    
            entries = doc.getDatabaseEntries();
    
    tjc's avatar
    tjc committed
            
    
            final DatabaseTreeNode top = new DatabaseTreeNode("");
    
    tjc's avatar
    tjc committed
            createNodes(top, doc, entries);
    
            return new DatabaseJTree(top);
          }
          catch(ConnectException e)
          {
            entry_source.setLocation(true);
          }
          catch(SQLException e)
          {
            entry_source.setLocation(true);
          }
          catch(RuntimeException p)
          {
            entry_source.setLocation(true);
          }
        }
    
    tjc's avatar
    tjc committed
    
    
        return null;
      }
    
    
      /**
       * Create the nodes of the organism JTree
       * @param top       root node
       * @param schema    <code>List</code>
    
       * @param doc       DatabaseDocument
    
       * @param organism  sequences collection
       */
    
    tjc's avatar
    tjc committed
      private void createNodes(DatabaseTreeNode top,
    
                               DatabaseDocument doc,
    
    tjc's avatar
    tjc committed
                               HashMap entries)
    
      {
        final Object v_organism[] = entries.keySet().toArray();
    
    tjc's avatar
    tjc committed
        
    
        final int v_organism_size = v_organism.length;
    
    tjc's avatar
    tjc committed
        Arrays.sort(v_organism, new Comparator()
        {
          public int compare(Object o1, Object o2)
          {
            return ((String)o1).compareToIgnoreCase( (String)o2 );
          } 
        });
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        final List organisms = new Vector();
        for(int i = 0; i < v_organism_size; i++)
        {
          String seqNames[]  = ((String)v_organism[i]).split("-");
          if(!organisms.contains(seqNames[0]))
            organisms.add(seqNames[0]);
        }
    
    
    tjc's avatar
    tjc committed
        int start = 0;
        boolean seen;
    
    tjc's avatar
    tjc committed
        String seqFullName;
        DatabaseTreeNode schema_node;
        DatabaseTreeNode seq_node;
        DatabaseTreeNode typ_node;
    
    tjc's avatar
    tjc committed
        for(int i=0; i<organisms.size(); i++)
    
        {
          int nchild = 0;
    
    tjc's avatar
    tjc committed
          String name = (String)organisms.get(i);
    
    tjc's avatar
    tjc committed
          seen = false;
    
          
          schema_node = new DatabaseTreeNode(name);
    
    tjc's avatar
    tjc committed
          final HashMap seq_type_node = new HashMap();
    
    tjc's avatar
    tjc committed
          for(int j = start; j < v_organism_size; j++)
    
    tjc's avatar
    tjc committed
            seqFullName = (String)v_organism[j];
            String seqNames[]  = seqFullName.split("-");
    
            if(seqNames[0].trim().toLowerCase().equals(name.toLowerCase().trim()))
    
    tjc's avatar
    tjc committed
              final String featureId = (String)entries.get(seqFullName);
    
    tjc's avatar
    tjc committed
              
    
    tjc's avatar
    tjc committed
              final String schema = seqNames[0].trim();
              String type = seqNames[1].trim();
              String thisSeqName = seqNames[2].trim();
    
    
              if(!seq_type_node.containsKey(type))
              {
                typ_node = new DatabaseTreeNode(type);
                seq_type_node.put(type, typ_node);
                schema_node.add(typ_node);
              }
              else
                typ_node = (DatabaseTreeNode) seq_type_node.get(type);
    
    
    tjc's avatar
    tjc committed
              seq_node = new DatabaseTreeNode(thisSeqName,
    
                                              featureId, schema, 
                                              doc.getUserName(),
                                              doc.isSingleSchema());
    
              typ_node.add(seq_node);
              nchild++;
    
    tjc's avatar
    tjc committed
              
    
    tjc's avatar
    tjc committed
              start = j;
              seen = true;
    
    tjc's avatar
    tjc committed
            else if(seen)
              break;
    
          }
          if(nchild > 0)
            top.add(schema_node);
        }
      }
      
    
    tjc's avatar
    tjc committed
      /**
       *  An InputStreamProgressListener used to update the error label with the
       *  current number of chars read.
       **/
      private final InputStreamProgressListener stream_progress_listener =
        new InputStreamProgressListener() 
      {
        public void progressMade(final InputStreamProgressEvent event) 
        {
          final int char_count = event.getCharCount();
          if(char_count == -1) 
            status_line.setText("");
          else 
            status_line.setText("chars read so far: " + char_count);
        }
    
        public void progressMade(String progress)
        {
          status_line.setText(progress);
        }
      };