Skip to content
Snippets Groups Projects
EditMenu.java 118 KiB
Newer Older
  • Learn to ignore specific revisions
  • tjc's avatar
    tjc committed
        text_requester.addTextRequesterListener (new TextRequesterListener () {
          public void actionPerformed (final TextRequesterEvent event) {
            if (event.getType () == TextRequesterEvent.CANCEL) {
              return;
            }
    
            final String bases_string = event.getRequesterText ().trim ();
    
            if (bases_string.length () == 0) {
              new MessageDialog (getParentFrame (), "no bases inserted");
              return;
            }
    
            try {
              // addBases () is static and uses the strand reference from the
              // start Marker to decide which Strand to edit
              Strand.addBases (range.getStart (), bases_string);
            } catch (ReadOnlyException e) {
              new MessageDialog (getParentFrame (),
                                 "sorry the bases are read only");
              return;
            } catch (org.biojava.bio.symbol.IllegalSymbolException e) {
              new MessageDialog (getParentFrame (),
                                 "sorry - new sequence contains non-IUB base " +
                                 "codes");
              return;
            }
          }
        });
    
    
        text_requester.setVisible(true);
    
    tjc's avatar
    tjc committed
      }
    
    
      /**
       *  Ask the user for some bases and then add them at the start of the
       *  selected range.
       **/
      private void addBasesFromFile () {
        if (!checkForSelectionRange ()) {
          return;
        }
    
        if (getEntryGroup ().isReadOnly ()) {
          new MessageDialog (getParentFrame (),
                             "one of the current entries or features is " +
                             "read-only - connot continue");
          return;
        }
    
        final MarkerRange range = getSelection ().getMarkerRange ();
    
        // XXX add an InputStreamProgressListener
        final EntrySourceVector entry_sources =
          Utilities.getEntrySources (getParentFrame (), null);
    
        EntrySource filesystem_entry_source = null;
    
        for (int source_index = 0 ;
             source_index < entry_sources.size () ;
             ++source_index) {
          final EntrySource this_source =
            entry_sources.elementAt (source_index);
    
          if (this_source.isFullEntrySource ()) {
            continue;
          }
    
          if (this_source.getSourceName ().equals ("Filesystem")) {
            filesystem_entry_source = this_source;
          }
        }
    
        if (filesystem_entry_source == null) {
          throw new Error ("internal error - can't find a file system to read " +
                           "from");
        }
    
        try {
          final Entry new_entry = filesystem_entry_source.getEntry (true);
    
          final Bases bases = new_entry.getBases ();
    
          final String bases_string = bases.toString ();
    
          if (bases_string.length () == 0) {
            new MessageDialog (getParentFrame (), "no bases inserted");
            return;
          }
    
          // addBases () is static and uses the strand reference from the
          // start Marker to decide which Strand to edit
          Strand.addBases (range.getStart (), bases_string);
        } catch (ReadOnlyException e) {
          new MessageDialog (getParentFrame (),
                             "sorry the bases are read only");
          return;
        } catch (IOException e) {
          new MessageDialog (getParentFrame (),
                             "error while reading: " + e.getMessage ());
          return;
        } catch (OutOfRangeException e) {
          new MessageDialog (getParentFrame (),
                             "out of range exception while reading: " +
                             e.getMessage ());
          return;
        } catch (NoSequenceException e) {
          new MessageDialog (getParentFrame (),
                             "sorry the file did not contain any sequence");
          return;
        } catch (org.biojava.bio.symbol.IllegalSymbolException e) {
          new MessageDialog (getParentFrame (),
                             "sorry - new sequence contains non-IUB base " +
                             "codes");
          return;
        }
      }
    
      /**
       *  Add a qualifier to the given features.  The qualifier will normally be a
       *  gene name.
       *  @param prefix_string prefix of the new qualifier eg. SPAC
       *  @param start_number The number to start counting at eg. 1 give SPAC0001
       *    for the first CDS
       *  @param increment The amount to increment by at each gene.
       *  @param qualifier_name The name of the qualifier to add
       *  @param tag_complement_names If True a lowercase "c" will be appended to
       *    the new qualifier values on the reverse strand. 
       **/
      private void autoGeneNameHelper (final FeatureVector features_to_name,
                                       final String prefix_string,
                                       final int start_number,
                                       final int increment,
                                       final String qualifier_name,
    
    tjc's avatar
    tjc committed
                                       final boolean tag_complement_names,
                                       final int format_value) {
    
    tjc's avatar
    tjc committed
        try {
          entry_group.getActionController ().startAction ();
    
    
    tjc's avatar
    tjc committed
          String fmt = "";
          for(int i=0; i<format_value; i++)
            fmt = fmt.concat("0");
          
          NumberFormat formatter = new DecimalFormat(fmt);
          
    
    tjc's avatar
    tjc committed
          int current_number = start_number;
    
          for (int i = 0 ; i < features_to_name.size () ; ++i) {
            final Feature this_feature = features_to_name.elementAt (i);
    
    
    tjc's avatar
    tjc committed
            //final Key key = this_feature.getKey ();
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
              final String number_string = formatter.format(current_number);
          
              /*if (current_number < 10) {
    
    tjc's avatar
    tjc committed
                number_string = "000" + current_number;
              } else {
                if (current_number < 100) {
                  number_string = "00" + current_number;
                } else {
                  if (current_number < 1000) {
                    number_string = "0" + current_number;
                  } else {
                    number_string = String.valueOf (current_number);
                  }
                }
    
    tjc's avatar
    tjc committed
              }*/
    
    tjc's avatar
    tjc committed
    
              try {
                final Qualifier new_qualifier =
                  new Qualifier (qualifier_name, prefix_string +
                                 number_string +
                                 (!tag_complement_names ||
                                  this_feature.isForwardFeature () ?
                                  "" :
                                  "c"));
    
                this_feature.addQualifierValues (new_qualifier);
              } catch (EntryInformationException e) {
                new MessageDialog (getParentFrame (),
                                   "/" + qualifier_name +
                                   " not supported by this entry " +
                                   "- cannot continue");
                return;
              } catch (ReadOnlyException e) {
                new MessageDialog (getParentFrame (),
                                   "one of the features is in a read-only " +
                                   "entry - cannot continue");
                return;
              }
    
              current_number += increment;
    
    tjc's avatar
    tjc committed
          }
        } finally {
          entry_group.getActionController ().endAction ();
        }
      }
    
      /**
       *  Automatically create gene names for all CDS features in the active
       *  entries.
       **/
      private void autoGeneName () {
        if (!checkForSelectionFeatures (getParentFrame (), getSelection ())) {
          return;
        }
    
        final FeatureVector features_to_name = getSelection ().getAllFeatures ();
    
        if (getReadOnlyFeatures (features_to_name).size () > 0) {
          new MessageDialog (getParentFrame (),
                             "one or more of the current features is " +
                             "read-only - cannot continue");
          return;
        }
    
        final TextDialog prefix_dialog =
          new TextDialog (getParentFrame (),
                          "enter the start characters of the new gene names:",
                          18, "");
    
        final String prefix_text = prefix_dialog.getText ();
    
        if (prefix_text == null) {
          return;
        }
    
        final String prefix_string = prefix_text.trim ();
    
        if (prefix_string.length () == 0) {
          new MessageDialog (getParentFrame (), "no prefix given");
          return;
        }
    
        final TextDialog start_number_dialog =
          new TextDialog (getParentFrame (),
                          "start counting at:", 18, "1");
    
        final String start_number_text = start_number_dialog.getText ();
    
        if (start_number_text == null) {
          return;
        }
    
        String start_string = start_number_text.trim ();
    
        if (start_string.length () == 0) {
          new MessageDialog (getParentFrame (), "no start given");
          return;
        }
    
        final int start_value;
    
        try {
          start_value = Integer.valueOf (start_string).intValue ();
        } catch (NumberFormatException e) {
          new MessageDialog (getParentFrame (),
                             "this is not a number: " + start_string);
          return;
        }
    
        final TextDialog increment_dialog =
          new TextDialog (getParentFrame (),
                          "increment number by:", 18, "1");
    
        final String increment_text = increment_dialog.getText ();
    
        if (increment_text == null) {
          return;
        }
    
        String increment_string = increment_text.trim ();
    
        if (increment_string.length () == 0) {
          new MessageDialog (getParentFrame (), "no increment given");
          return;
        }
    
        final int increment_value;
    
        try {
          increment_value = Integer.valueOf (increment_string).intValue ();
        } catch (NumberFormatException e) {
          new MessageDialog (getParentFrame (),
                             "this is not a number: " + increment_string);
          return;
        }
    
        final TextDialog qualifier_name_dialog =
          new TextDialog (getParentFrame (),
                          "enter a qualifier name to use",
                          18, "gene");
    
        final String qualifier_name_text = qualifier_name_dialog.getText ();
    
        if (qualifier_name_text == null) {
          return;
        }
    
        final String qualifier_name_string = qualifier_name_text.trim ();
    
        if (qualifier_name_string.length () == 0) {
          new MessageDialog (getParentFrame (), "no qualifier name given");
          return;
        }
    
        final YesNoDialog complement_tag_dialog =
          new YesNoDialog (getParentFrame (),
                           "append \"c\" to names of reverse strand features?");
    
    
    tjc's avatar
    tjc committed
        final TextDialog format_dialog =
          new TextDialog (getParentFrame (),
    
    tjc's avatar
    tjc committed
                          "number of digits in the name, e.g. 5, pads with " +
                          "zeros: 00009, 00010 ....",
    
    tjc's avatar
    tjc committed
                          18, "5");
        
        int format_value;
    
        try {
          format_value = Integer.valueOf (format_dialog.getText().trim()).intValue ();
        } catch (NumberFormatException e) {
          new MessageDialog (getParentFrame (),
                             "this is not a number: " + format_dialog.getText());
          return;
        }
        
        if(format_value < 0)
          format_value = -format_value;
        
    
        autoGeneNameHelper(features_to_name,
                           prefix_string, start_value, increment_value,
                           qualifier_name_string,
    
    tjc's avatar
    tjc committed
                           complement_tag_dialog.getResult(), format_value);
    
    tjc's avatar
    tjc committed
      }
    
      /**
       *  Helper function for fixGeneNames().  Add the gene name from the CDS to
       *  neighbouring/overlapping mRNA, intron, exon, gene, 5'UTR and 3'UTR
       *  features.  Warn about inconsistencies.
       *  @return true if all went well, false if fixing should stop immediately
       **/
    
      private static boolean fixGeneNamesHelper(final JFrame frame,
                                                final EntryGroup entry_group,
    
                                                final Feature cds_to_fix,
                                                final String name) 
    
    tjc's avatar
    tjc committed
          final String message =
            "one or more of the of the selected features are read only " +
            "- cannot continue";
    
          new MessageDialog(frame, message);
    
    tjc's avatar
    tjc committed
          return false;
        }
    
        try 
        {
          final Strand cds_to_fix_strand = cds_to_fix.getStrand();
          Marker cds_start_marker = cds_to_fix.getFirstBaseMarker();
          Marker cds_end_marker = cds_to_fix.getLastBaseMarker();
    
    tjc's avatar
    tjc committed
    
          // move the start one base back and the end one base forward so that
          // when we call getFeaturesInRange() we get the UTRs
    
    
          try 
          {
            cds_start_marker = cds_start_marker.moveBy(-1);
          }
          catch(OutOfRangeException _) 
          {
    
    tjc's avatar
    tjc committed
            // ignore and use the original cds_start_marker
          }
    
    
          try 
          {
            cds_end_marker = cds_end_marker.moveBy(1);
          } 
          catch(OutOfRangeException _) 
          {
    
    tjc's avatar
    tjc committed
            // ignore and use the original cds_end_marker
          }
    
          final Range search_range;
    
    
          if(cds_start_marker.getRawPosition() < cds_end_marker.getRawPosition())
          {
            search_range =
              new Range(cds_start_marker.getRawPosition(),
                        cds_end_marker.getRawPosition());
          }
          else
          {
    
    tjc's avatar
    tjc committed
            search_range =
    
              new Range(cds_end_marker.getRawPosition(),
                       cds_start_marker.getRawPosition());
          }
    
    tjc's avatar
    tjc committed
    
          final FeatureVector features_in_range =
    
            entry_group.getFeaturesInRange(search_range);
    
    tjc's avatar
    tjc committed
    
          final FeatureVector features_to_change =
    
            new FeatureVector();
    
          for(int i = 0 ; i < features_in_range.size() ; ++i) 
          {
            final Feature this_feature = features_in_range.elementAt(i);
    
            if(this_feature.getStrand() == cds_to_fix_strand &&
               (this_feature.isCDS() ||
                this_feature.getKey().equals("mRNA") ||
                this_feature.getKey().equals("intron") ||
                this_feature.getKey().equals("exon") ||
                 this_feature.getKey().equals("5'UTR") &&
                 (cds_to_fix.getFirstBase() ==
                  this_feature.getLastBase() + 1) ||
                 this_feature.getKey().equals("3'UTR") &&
                 (cds_to_fix.getLastBase() + 1 ==
                  this_feature.getFirstBase()) ||
                 this_feature.getKey().equals("gene"))) 
            {
              if(this_feature.isReadOnly()) 
              {
    
    tjc's avatar
    tjc committed
                final String message =
                  "one or more of the of the overlapping features are read only " +
                  "- cannot continue";
    
                new MessageDialog(frame, message);
    
    tjc's avatar
    tjc committed
                return false;
              }
    
              
              
              // for exons check they are in this cds's range
              if(this_feature.getKey().equals("exon"))
              {
                Range exon_range = this_feature.getMaxRawRange();
                RangeVector ranges = cds_to_fix.getLocation().getRanges();
                
                for(int j=0; j<ranges.size(); j++)
                {
                  Range range = (Range)ranges.get(j);
                  if(exon_range.equals(range))
                  {
                    features_to_change.add(this_feature);
                    break;
                  }
                }
              }
              else
                features_to_change.add(this_feature);
    
    tjc's avatar
    tjc committed
            }
          }
    
    
          final FeatureVector overlapping_cds_features = new FeatureVector();
          for(int i = 0 ; i < features_to_change.size() ; ++i) 
          {
            final Feature this_test_feature = features_to_change.elementAt(i);
            if(this_test_feature != cds_to_fix && this_test_feature.isCDS())
            {
              overlapping_cds_features.add(this_test_feature);
              features_to_change.remove(this_test_feature);
    
    tjc's avatar
    tjc committed
            }
          }
    
    
          if(overlapping_cds_features.size() > 0) 
          {
    
    tjc's avatar
    tjc committed
            final String message =
    
              "your CDS (" + cds_to_fix.getIDString() +
              ") overlaps " + overlapping_cds_features.size() +
    
    tjc's avatar
    tjc committed
              " other CDS feature" +
    
              (overlapping_cds_features.size() == 1 ?
    
    tjc's avatar
    tjc committed
               "" : "s") + " - continue?";
    
            final YesNoDialog dialog =
    
              new YesNoDialog(frame, message);
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
              return false;
    
    tjc's avatar
    tjc committed
          final StringVector gene_names = new StringVector ();
    
          for(int i = 0; i < features_to_change.size(); ++i)
          {
    
    tjc's avatar
    tjc committed
            final Feature test_feature =
    
              features_to_change.elementAt(i);
    
    tjc's avatar
    tjc committed
    
            final StringVector test_feature_gene_names =
    
              test_feature.getValuesOfQualifier(name);
    
    tjc's avatar
    tjc committed
    
    
            if(test_feature_gene_names != null) 
            {
              for(int j = 0; j < test_feature_gene_names.size(); ++j)
             {
    
    tjc's avatar
    tjc committed
                final String this_gene_name =
    
    tjc's avatar
    tjc committed
                  (String)test_feature_gene_names.elementAt(j);
    
    tjc's avatar
    tjc committed
    
    
                if(!gene_names.contains(this_gene_name))
    
    tjc's avatar
    tjc committed
                  gene_names.add (this_gene_name);
              }
            }
          }
    
    
          // ignore this feature, but continue with the other features
          if (gene_names.size () == 0)
    
    tjc's avatar
    tjc committed
            return true;
    
    
          for(int i = 0; i < features_to_change.size(); ++i)
          {
            final Feature this_feature = features_to_change.elementAt(i);
    
            final Qualifier qualifier = new Qualifier(name, gene_names);
    
            this_feature.setQualifier(qualifier);
          }
        } 
        catch(OutOfRangeException e) 
        {
          throw new Error("internal error - unexpected exception: " + e);
        } 
        catch(InvalidRelationException e) 
        {
          throw new Error("internal error - unexpected exception: " + e);
        } 
        catch(EntryInformationException e) 
        {
          throw new Error("internal error - unexpected exception: " + e);
        } 
        catch(ReadOnlyException e) 
        {
          throw new Error("internal error - unexpected exception: " + e);
    
    tjc's avatar
    tjc committed
        }
    
        return true;
      }
    
      /**
       *  For each selected CDS, add the gene name from the CDS to
       *  neighbouring/overlapping mRNA, intron, exon, gene, 5'UTR and 3'UTR
       *  features.  Warn about inconsistencies.
       *  @param frame The Frame to use for MessageDialog components.
       *  @param selection The Selection that the commands in the menu will
       *    operate on.
       **/
    
      private static void fixGeneNames(final JFrame frame,
                                      final EntryGroup entry_group,
                                      final Selection selection) 
      {
        try 
        {
          entry_group.getActionController().startAction();
          final FeatureVector features_to_fix = selection.getAllFeatures();
    
    tjc's avatar
    tjc committed
          int cds_features_found = 0;
    
    
          StringVector names = Options.getOptions().getSystematicQualifierNames();
          JList types = new JList(names);
          types.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
          types.setSelectedValue("gene", true);
          JOptionPane.showMessageDialog(frame, types,
                  "Qualifier to Transfer", JOptionPane.QUESTION_MESSAGE);
          String name = (String) types.getSelectedValue();
          
    
          for(int i = 0; i < features_to_fix.size(); ++i)
          {
            final Feature selection_feature = features_to_fix.elementAt(i);
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
              ++cds_features_found;
    
              if(!fixGeneNamesHelper(frame, entry_group, selection_feature, name))
    
    tjc's avatar
    tjc committed
                return;
            }
          }
    
    
          if(cds_features_found == 0) 
            new MessageDialog(frame, "no CDS features selected");
        } 
        finally
        {
    
    tjc's avatar
    tjc committed
          entry_group.getActionController ().endAction ();
        }
      }
    
      /**
       *  Return the EntryGroup that was passed to the constructor.
       **/
    
      private EntryGroup getEntryGroup() 
      {
    
    tjc's avatar
    tjc committed
        return entry_group;
      }
    
      /**
       *  This method sends an GotoEvent to all the GotoEvent listeners that will
       *  make the first base of the selection visible.
       **/
    
      private void makeSelectionStartVisible() 
      {
        final GotoEvent new_event = new GotoEvent(this,
                                          getSelection().getStartBaseOfSelection());
        goto_event_source.sendGotoEvent(new_event);
    
    tjc's avatar
    tjc committed
      }
    
      /**
       *  Returns a Vector containing those features in the given vector of
       *  features which are read only or are in a read only entry.
       **/
    
      private static FeatureVector getReadOnlyFeatures(final FeatureVector features)
      {
        final FeatureVector return_vector = new FeatureVector();
    
    tjc's avatar
    tjc committed
    
    
        for(int i = 0; i < features.size(); ++i) 
        {
          final Feature this_feature = features.elementAt(i);
          if(this_feature.isReadOnly()) 
            return_vector.add(this_feature);
    
    tjc's avatar
    tjc committed
        }
    
        return return_vector;
      }
    }