JAL-1942 JAL-1479 DBRefFetcher refactor
[jalview.git] / src / jalview / ws / DBRefFetcher.java
index 12b4158..2e0197c 100644 (file)
@@ -1,19 +1,21 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
- * Copyright (C) 2014 The Jalview Authors
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
  * 
  * This file is part of Jalview.
  * 
  * Jalview 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 3 of the License, or (at your option) any later version.
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
  *  
  * Jalview 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 Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
 package jalview.ws;
@@ -26,11 +28,12 @@ import jalview.datamodel.DBRefSource;
 import jalview.datamodel.Mapping;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
-import jalview.gui.AlignFrame;
 import jalview.gui.CutAndPasteTransfer;
 import jalview.gui.Desktop;
+import jalview.gui.FeatureSettings;
 import jalview.gui.IProgressIndicator;
 import jalview.gui.OOMWarning;
+import jalview.util.MessageManager;
 import jalview.ws.dbsources.das.api.jalviewSourceI;
 import jalview.ws.seqfetcher.DbSourceProxy;
 
@@ -77,59 +80,64 @@ public class DBRefFetcher implements Runnable
 
   private SequenceI[] alseqs;
 
-  public DBRefFetcher()
-  {
-  }
-
   /**
-   * Creates a new SequenceFeatureFetcher object and fetches from the currently
-   * selected set of databases.
-   * 
-   * @param seqs
-   *          fetch references for these sequences
-   * @param af
-   *          the parent alignframe for progress bar monitoring.
+   * when true - retrieved sequences will be trimmed to cover longest derived
+   * alignment sequence
    */
-  public DBRefFetcher(SequenceI[] seqs, AlignFrame af)
+  private boolean trimDsSeqs = true;
+
+  public DBRefFetcher()
   {
-    this(seqs, af, null);
   }
 
   /**
-   * Creates a new SequenceFeatureFetcher object and fetches from the currently
-   * selected set of databases.
+   * Creates a new DBRefFetcher object and fetches from the currently selected
+   * set of databases, if this is null then it fetches based on feature settings
    * 
    * @param seqs
-   *          fetch references for these sequences
-   * @param af
-   *          the parent alignframe for progress bar monitoring.
+   *          fetch references for these SequenceI array
+   * @param progressIndicatorFrame
+   *          the frame for progress bar monitoring
    * @param sources
-   *          array of database source strings to query references from
+   *          array of DbSourceProxy to query references form
+   * @param featureSettings
+   *          FeatureSettings to get alternative DbSourceProxy from
+   * @param isNucleotide
+   *          indicates if the array of SequenceI are Nucleotides or not
    */
-  public DBRefFetcher(SequenceI[] seqs, AlignFrame af,
-          DbSourceProxy[] sources)
+  public DBRefFetcher(SequenceI[] seqs,
+          IProgressIndicator progressIndicatorFrame,
+          DbSourceProxy[] sources, FeatureSettings featureSettings, boolean isNucleotide)
   {
-    this.af = af;
+    this.af = progressIndicatorFrame;
     alseqs = new SequenceI[seqs.length];
     SequenceI[] ds = new SequenceI[seqs.length];
     for (int i = 0; i < seqs.length; i++)
     {
       alseqs[i] = seqs[i];
       if (seqs[i].getDatasetSequence() != null)
+      {
         ds[i] = seqs[i].getDatasetSequence();
+      }
       else
+      {
         ds[i] = seqs[i];
+      }
     }
     this.dataset = ds;
     // TODO Jalview 2.5 lots of this code should be in the gui package!
-    sfetcher = jalview.gui.SequenceFetcher.getSequenceFetcherSingleton(af);
+    sfetcher = jalview.gui.SequenceFetcher
+            .getSequenceFetcherSingleton(progressIndicatorFrame);
+    // set default behaviour for transferring excess sequence data to the
+    // dataset
+    trimDsSeqs = Cache.getDefault("TRIM_FETCHED_DATASET_SEQS", true);
     if (sources == null)
     {
       // af.featureSettings_actionPerformed(null);
       String[] defdb = null, otherdb = sfetcher
               .getDbInstances(jalview.ws.dbsources.das.datamodel.DasSequenceSource.class);
       List<DbSourceProxy> selsources = new ArrayList<DbSourceProxy>();
-      Vector dasselsrc = (af.featureSettings != null) ? af.featureSettings
+      Vector dasselsrc = (featureSettings != null) ? featureSettings
               .getSelectedSources() : new jalview.gui.DasSourceBrowser()
               .getSelectedSources();
       Enumeration<jalviewSourceI> en = dasselsrc.elements();
@@ -147,7 +155,7 @@ public class DBRefFetcher implements Runnable
         }
       }
       // select appropriate databases based on alignFrame context.
-      if (af.getViewport().getAlignment().isNucleotide())
+      if (isNucleotide)
       {
         defdb = DBRefSource.DNACODINGDBS;
       }
@@ -267,15 +275,19 @@ public class DBRefFetcher implements Runnable
   /**
    * DOCUMENT ME!
    */
+  @Override
   public void run()
   {
     if (dbSources == null)
     {
-      throw new Error("Implementation error. Must initialise dbSources");
+      throw new Error(
+              MessageManager
+                      .getString("error.implementation_error_must_init_dbsources"));
     }
     running = true;
     long startTime = System.currentTimeMillis();
-    af.setProgressBar("Fetching db refs", startTime);
+    af.setProgressBar(MessageManager.getString("status.fetching_db_refs"),
+            startTime);
     try
     {
       if (Cache.getDefault("DBREFFETCH_USEPICR", false))
@@ -371,7 +383,7 @@ public class DBRefFetcher implements Runnable
             if (retrieved != null)
             {
               transferReferences(sdataset, dbsource.getDbSource(),
-                      retrieved);
+                      retrieved, trimDsSeqs);
             }
           }
           else
@@ -381,8 +393,8 @@ public class DBRefFetcher implements Runnable
             {
               SequenceI sequence = dataset[seqIndex];
               DBRefEntry[] uprefs = jalview.util.DBRefUtils.selectRefs(
-                      sequence.getDBRef(), new String[]
-                      { dbsource.getDbSource() }); // jalview.datamodel.DBRefSource.UNIPROT
+                      sequence.getDBRefs(),
+                      new String[] { dbsource.getDbSource() }); // jalview.datamodel.DBRefSource.UNIPROT
               // });
               // check for existing dbrefs to use
               if (uprefs != null && uprefs.length > 0)
@@ -450,17 +462,20 @@ public class DBRefFetcher implements Runnable
     } // all databases have been queries.
     if (sbuffer.length() > 0)
     {
-      output.setText("Your sequences have been verified against known sequence databases. Some of the ids have been\n"
-              + "altered, most likely the start/end residue will have been updated.\n"
-              + "Save your alignment to maintain the updated id.\n\n"
+      output.setText(MessageManager
+              .getString("label.your_sequences_have_been_verified")
               + sbuffer.toString());
-      Desktop.addInternalFrame(output, "Sequence names updated ", 600, 300);
+      Desktop.addInternalFrame(output,
+              MessageManager.getString("label.sequence_names_updated"),
+              600, 300);
       // The above is the dataset, we must now find out the index
       // of the viewed sequence
 
     }
 
-    af.setProgressBar("DBRef search completed", startTime);
+    af.setProgressBar(
+            MessageManager.getString("label.dbref_search_completed"),
+            startTime);
     // promptBeforeBlast();
 
     running = false;
@@ -471,11 +486,14 @@ public class DBRefFetcher implements Runnable
    * Verify local sequences in seqRefs against the retrieved sequence database
    * records.
    * 
+   * @param trimDatasetSeqs
+   * 
    */
   void transferReferences(Vector sdataset, String dbSource,
-          AlignmentI retrievedAl) // File
+          AlignmentI retrievedAl, boolean trimDatasetSeqs) // File
   // file)
   {
+    System.out.println("trimming ? " + trimDatasetSeqs);
     if (retrievedAl == null || retrievedAl.getHeight() == 0)
     {
       return;
@@ -499,8 +517,7 @@ public class DBRefFetcher implements Runnable
       Vector sequenceMatches = new Vector();
       // look for corresponding accession ids
       DBRefEntry[] entryRefs = jalview.util.DBRefUtils.selectRefs(
-              entry.getDBRef(), new String[]
-              { dbSource });
+              entry.getDBRefs(), new String[] { dbSource });
       if (entryRefs == null)
       {
         System.err
@@ -567,17 +584,18 @@ public class DBRefFetcher implements Runnable
         // no existing references
         // TODO: test for legacy where uniprot or EMBL refs exist but no
         // mappings are made (but content matches retrieved set)
-        boolean updateRefFrame = sequence.getDBRef() == null
-                || sequence.getDBRef().length == 0;
+        boolean updateRefFrame = sequence.getDBRefs() == null
+                || sequence.getDBRefs().length == 0;
+        // TODO:
         // verify sequence against the entry sequence
 
         String nonGapped = AlignSeq.extractGaps("-. ",
                 sequence.getSequenceAsString()).toUpperCase();
 
         int absStart = entrySeq.indexOf(nonGapped);
-        int mapStart = entry.getStart();
-        jalview.datamodel.Mapping mp;
+        Mapping mp;
 
+        final int sequenceStart = sequence.getStart();
         if (absStart == -1)
         {
           // Is local sequence contained in dataset sequence?
@@ -597,12 +615,10 @@ public class DBRefFetcher implements Runnable
           // absStart = 0;
           // create valid mapping between matching region of local sequence and
           // the mapped sequence
-          mp = new Mapping(null, new int[]
-          { sequence.getStart() + absStart,
-              sequence.getStart() + absStart + entrySeq.length() - 1 },
-                  new int[]
-                  { entry.getStart(),
-                      entry.getStart() + entrySeq.length() - 1 }, 1, 1);
+          mp = new Mapping(null, new int[] { sequenceStart + absStart,
+              sequenceStart + absStart + entrySeq.length() - 1 }, new int[]
+          { entry.getStart(), entry.getStart() + entrySeq.length() - 1 },
+                  1, 1);
           updateRefFrame = false; // mapping is based on current start/end so
           // don't modify start and end
         }
@@ -625,7 +641,7 @@ public class DBRefFetcher implements Runnable
             if (sequence.getSequenceFeatures() != null)
             {
               SequenceFeature[] sf = sequence.getSequenceFeatures();
-              int start = sequence.getStart();
+              int start = sequenceStart;
               int end = sequence.getEnd();
               int startShift = 1 - absStart - start; // how much the features
                                                      // are
@@ -647,13 +663,23 @@ public class DBRefFetcher implements Runnable
                 + " from " + dbSource + " sequence : " + entry.getName());
         sequence.transferAnnotation(entry, mp);
         // unknownSequences.remove(sequence);
-        int absEnd = absStart + nonGapped.length();
-        absStart += 1;
+        absStart += entry.getStart();
+        int absEnd = absStart + nonGapped.length() - 1;
+        if (!trimDatasetSeqs)
+        {
+          // insert full length sequence from record
+          sequence.setSequence(entry.getSequenceAsString());
+          sequence.setStart(entry.getStart());
+        }
         if (updateRefFrame)
         {
           // finally, update local sequence reference frame if we're allowed
-          sequence.setStart(absStart);
-          sequence.setEnd(absEnd);
+          if (trimDatasetSeqs)
+          {
+            // just fix start/end
+            sequence.setStart(absStart);
+            sequence.setEnd(absEnd);
+          }
           // search for alignment sequences to update coordinate frame for
           for (int alsq = 0; alsq < alseqs.length; alsq++)
           {
@@ -704,7 +730,7 @@ public class DBRefFetcher implements Runnable
     for (int i = 0; sequencesArray != null && i < sequencesArray.length; i++)
     {
       nseq.addElement(sequencesArray[i]);
-      DBRefEntry dbr[] = sequencesArray[i].getDBRef();
+      DBRefEntry dbr[] = sequencesArray[i].getDBRefs();
       jalview.datamodel.Mapping map = null;
       for (int r = 0; (dbr != null) && r < dbr.length; r++)
       {