JAL-4061 support incremental search of features
authorJim Procter <j.procter@dundee.ac.uk>
Thu, 15 Sep 2022 17:19:35 +0000 (18:19 +0100)
committerJim Procter <j.procter@dundee.ac.uk>
Thu, 15 Sep 2022 17:19:35 +0000 (18:19 +0100)
src/jalview/analysis/Finder.java
test/jalview/analysis/FinderTest.java

index 181cc9f..6061d76 100644 (file)
@@ -73,6 +73,16 @@ public class Finder implements FinderI
   private int residueIndex;
 
   /*
+   * last feature matched when incrementally searching sequence features
+   */
+  private SequenceFeature lastFeature;
+
+  /*
+   * last sequenceIndex used when lastFeature was discovered
+   */
+  private int lastFeatureSequenceIndex;
+
+  /*
    * the true sequence position of the start of the 
    * last sequence searched (when 'ignore hidden regions' does not apply)
    */
@@ -106,6 +116,8 @@ public class Finder implements FinderI
     /*
      * search from the start
      */
+    lastFeature = null;
+    lastFeatureSequenceIndex = 0;
     sequenceIndex = 0;
     residueIndex = -1;
 
@@ -117,6 +129,8 @@ public class Finder implements FinderI
      */
     sequenceIndex = 0;
     residueIndex = -1;
+    lastFeature = null;
+    lastFeatureSequenceIndex = 0;
   }
 
   @Override
@@ -134,6 +148,8 @@ public class Finder implements FinderI
        */
       sequenceIndex = 0;
       residueIndex = -1;
+      lastFeature = null;
+      lastFeatureSequenceIndex = 0;
     }
   }
 
@@ -387,8 +403,12 @@ public class Finder implements FinderI
       {
         if (matchFeatureDesc)
         {
-          // TODO - record last matched
           matched = searchSequenceFeatures(residueIndex, searchPattern);
+          if (matched)
+          {
+            return true;
+          }
+          lastFeature = null;
         }
         residueIndex = Integer.MAX_VALUE;
       }
@@ -557,28 +577,47 @@ public class Finder implements FinderI
    * sequence to the list of match ids, (but not as a duplicate). Answers true
    * if a match was added, else false.
    * 
-   * TODO: allow incremental searching (ie next feature matched after last)
-   * 
    * @param seq
    * @param searchPattern
    * @return
    */
   protected boolean searchSequenceFeatures(int from, Regex searchPattern)
   {
-    boolean matched = false;
+    if (lastFeatureSequenceIndex != sequenceIndex)
+    {
+      lastFeatureSequenceIndex = sequenceIndex;
+      lastFeature = null;
+    }
     SequenceI seq = viewport.getAlignment().getSequenceAt(sequenceIndex);
-
+    long fpos = 0;
     SequenceFeaturesI sf = seq.getFeatures();
     for (SequenceFeature feature : sf.getAllFeatures(null))
     {
+      fpos++;
+      if (lastFeature != null)
+      {
+        // iterate till we find last feature matched
+        if (lastFeature != feature)
+        {
+          continue;
+        }
+        else
+        {
+          lastFeature = null;
+          continue;
+        }
+      }
       if (searchPattern.search(feature.type) || (feature.description != null
               && searchPattern.search(feature.description)))
       {
         searchResults.addResult(seq, feature.getBegin(), feature.getEnd());
-        matched = true;
+        lastFeature = feature;
+        return true;
       }
     }
-    return matched;
+    residueIndex = Integer.MAX_VALUE;
+    lastFeature = null;
+    return false;
   }
 
   /**
index 62e219d..0220c36 100644 (file)
@@ -964,5 +964,29 @@ public class FinderTest
             seqs.get(2).getDatasetSequence());
     assertEquals(seqs.get(2).getStart(), 1);
     assertEquals(seqs.get(2).getEnd(), 3);
+
+    SequenceI sq = null;
+    // search feature descriptions incrementally
+    // assume same order as before
+    f.findNext("Feature", false, false, true, true);
+    assertEquals(f.getSearchResults().getCount(), 1);
+    sq = f.getSearchResults().getMatchingSubSequences().get(0);
+    assertEquals(sq.getSequenceAsString(),
+            seqs.get(0).getSequenceAsString());
+
+    // ..
+    f.findNext("Feature", false, false, true, true);
+    assertEquals(f.getSearchResults().getCount(), 1);
+    sq = f.getSearchResults().getMatchingSubSequences().get(0);
+    assertEquals(sq.getSequenceAsString(),
+            seqs.get(1).getSequenceAsString());
+
+    // ..
+    f.findNext("Feature", false, false, true, true);
+    assertEquals(f.getSearchResults().getCount(), 1);
+    sq = f.getSearchResults().getMatchingSubSequences().get(0);
+    assertEquals(sq.getSequenceAsString(),
+            seqs.get(2).getSequenceAsString());
+
   }
 }