JAL-2759 BoundedStartRegionIterator test
[jalview.git] / src / jalview / datamodel / Sequence.java
index 2ee412b..933c89d 100755 (executable)
@@ -38,8 +38,6 @@ import java.util.List;
 import java.util.ListIterator;
 import java.util.Vector;
 
-import com.stevesoft.pat.Regex;
-
 import fr.orsay.lri.varna.models.rna.RNA;
 
 /**
@@ -51,11 +49,6 @@ import fr.orsay.lri.varna.models.rna.RNA;
  */
 public class Sequence extends ASequence implements SequenceI
 {
-  private static final Regex limitrx = new Regex(
-          "[/][0-9]{1,}[-][0-9]{1,}$");
-
-  private static final Regex endrx = new Regex("[0-9]{1,}$");
-
   SequenceI datasetSequence;
 
   String name;
@@ -151,6 +144,10 @@ public class Sequence extends ASequence implements SequenceI
     checkValidRange();
   }
 
+  /**
+   * If 'name' ends in /i-j, where i >= j > 0 are integers, extracts i and j as
+   * start and end respectively and removes the suffix from the name
+   */
   void parseId()
   {
     if (name == null)
@@ -159,17 +156,37 @@ public class Sequence extends ASequence implements SequenceI
               "POSSIBLE IMPLEMENTATION ERROR: null sequence name passed to constructor.");
       name = "";
     }
-    // Does sequence have the /start-end signature?
-    if (limitrx.search(name))
+    int slashPos = name.lastIndexOf('/');
+    if (slashPos > -1 && slashPos < name.length() - 1)
     {
-      name = limitrx.left();
-      endrx.search(limitrx.stringMatched());
-      setStart(Integer.parseInt(limitrx.stringMatched().substring(1,
-              endrx.matchedFrom() - 1)));
-      setEnd(Integer.parseInt(endrx.stringMatched()));
+      String suffix = name.substring(slashPos + 1);
+      String[] range = suffix.split("-");
+      if (range.length == 2)
+      {
+        try
+        {
+          int from = Integer.valueOf(range[0]);
+          int to = Integer.valueOf(range[1]);
+          if (from > 0 && to >= from)
+          {
+            name = name.substring(0, slashPos);
+            setStart(from);
+            setEnd(to);
+            checkValidRange();
+          }
+        } catch (NumberFormatException e)
+        {
+          // leave name unchanged if suffix is invalid
+        }
+      }
     }
   }
 
+  /**
+   * Ensures that 'end' is not before the end of the sequence, that is,
+   * (end-start+1) is at least as long as the count of ungapped positions. Note
+   * that end is permitted to be beyond the end of the sequence data.
+   */
   void checkValidRange()
   {
     // Note: JAL-774 :
@@ -178,7 +195,7 @@ public class Sequence extends ASequence implements SequenceI
       int endRes = 0;
       for (int j = 0; j < sequence.length; j++)
       {
-        if (!jalview.util.Comparison.isGap(sequence[j]))
+        if (!Comparison.isGap(sequence[j]))
         {
           endRes++;
         }
@@ -396,7 +413,7 @@ public class Sequence extends ASequence implements SequenceI
   {
     if (pdbIds == null)
     {
-      pdbIds = new Vector<PDBEntry>();
+      pdbIds = new Vector<>();
       pdbIds.add(entry);
       return true;
     }
@@ -453,15 +470,15 @@ public class Sequence extends ASequence implements SequenceI
   }
 
   /**
-   * DOCUMENT ME!
+   * Sets the sequence name. If the name ends in /start-end, then the start-end
+   * values are parsed out and set, and the suffix is removed from the name.
    * 
-   * @param name
-   *          DOCUMENT ME!
+   * @param theName
    */
   @Override
-  public void setName(String name)
+  public void setName(String theName)
   {
-    this.name = name;
+    this.name = theName;
     this.parseId();
   }
 
@@ -1059,6 +1076,27 @@ public class Sequence extends ASequence implements SequenceI
     return map;
   }
 
+  /**
+   * Build a bitset corresponding to sequence gaps
+   * 
+   * @return a BitSet where set values correspond to gaps in the sequence
+   */
+  @Override
+  public BitSet gapBitset()
+  {
+    BitSet gaps = new BitSet(sequence.length);
+    int j = 0;
+    while (j < sequence.length)
+    {
+      if (jalview.util.Comparison.isGap(sequence[j]))
+      {
+        gaps.set(j);
+      }
+      j++;
+    }
+    return gaps;
+  }
+
   @Override
   public int[] findPositionMap()
   {
@@ -1082,7 +1120,7 @@ public class Sequence extends ASequence implements SequenceI
   @Override
   public List<int[]> getInsertions()
   {
-    ArrayList<int[]> map = new ArrayList<int[]>();
+    ArrayList<int[]> map = new ArrayList<>();
     int lastj = -1, j = 0;
     int pos = start;
     int seqlen = sequence.length;
@@ -1380,7 +1418,7 @@ public class Sequence extends ASequence implements SequenceI
   {
     if (this.annotation == null)
     {
-      this.annotation = new Vector<AlignmentAnnotation>();
+      this.annotation = new Vector<>();
     }
     if (!this.annotation.contains(annotation))
     {
@@ -1547,7 +1585,7 @@ public class Sequence extends ASequence implements SequenceI
       return null;
     }
 
-    Vector<AlignmentAnnotation> subset = new Vector<AlignmentAnnotation>();
+    Vector<AlignmentAnnotation> subset = new Vector<>();
     Enumeration<AlignmentAnnotation> e = annotation.elements();
     while (e.hasMoreElements())
     {
@@ -1705,7 +1743,7 @@ public class Sequence extends ASequence implements SequenceI
   public List<AlignmentAnnotation> getAlignmentAnnotations(String calcId,
           String label)
   {
-    List<AlignmentAnnotation> result = new ArrayList<AlignmentAnnotation>();
+    List<AlignmentAnnotation> result = new ArrayList<>();
     if (this.annotation != null)
     {
       for (AlignmentAnnotation ann : annotation)
@@ -1761,7 +1799,7 @@ public class Sequence extends ASequence implements SequenceI
     }
     synchronized (dbrefs)
     {
-      List<DBRefEntry> primaries = new ArrayList<DBRefEntry>();
+      List<DBRefEntry> primaries = new ArrayList<>();
       DBRefEntry[] tmp = new DBRefEntry[1];
       for (DBRefEntry ref : dbrefs)
       {