update spikes/mungo from JAL-3076 patch branch
[jalview.git] / src / jalview / util / MapList.java
index 81b9964..9f28ee1 100644 (file)
@@ -116,8 +116,17 @@ public class MapList
   {
     int hashCode = 31 * fromRatio;
     hashCode = 31 * hashCode + toRatio;
-    hashCode = 31 * hashCode + fromShifts.toArray().hashCode();
-    hashCode = 31 * hashCode + toShifts.toArray().hashCode();
+    for (int[] shift : fromShifts)
+    {
+      hashCode = 31 * hashCode + shift[0];
+      hashCode = 31 * hashCode + shift[1];
+    }
+    for (int[] shift : toShifts)
+    {
+      hashCode = 31 * hashCode + shift[0];
+      hashCode = 31 * hashCode + shift[1];
+    }
+
     return hashCode;
   }
 
@@ -318,6 +327,13 @@ public class MapList
     fromHighest = Integer.MIN_VALUE;
     for (int[] range : fromRange)
     {
+      if (range.length != 2)
+      {
+        // throw new IllegalArgumentException(range);
+        System.err.println(
+                "Invalid format for fromRange " + Arrays.toString(range)
+                + " may cause errors");
+      }
       fromLowest = Math.min(fromLowest, Math.min(range[0], range[1]));
       fromHighest = Math.max(fromHighest, Math.max(range[0], range[1]));
     }
@@ -326,6 +342,13 @@ public class MapList
     toHighest = Integer.MIN_VALUE;
     for (int[] range : toRange)
     {
+      if (range.length != 2)
+      {
+        // throw new IllegalArgumentException(range);
+        System.err.println("Invalid format for toRange "
+                + Arrays.toString(range)
+                + " may cause errors");
+      }
       toLowest = Math.min(toLowest, Math.min(range[0], range[1]));
       toHighest = Math.max(toHighest, Math.max(range[0], range[1]));
     }
@@ -1021,15 +1044,70 @@ public class MapList
 
     for (int[] range : map.getFromRanges())
     {
-      MappingUtils.addRange(range, fromShifts);
+      addRange(range, fromShifts);
     }
     for (int[] range : map.getToRanges())
     {
-      MappingUtils.addRange(range, toShifts);
+      addRange(range, toShifts);
     }
   }
 
   /**
+   * Adds the given range to a list of ranges. If the new range just extends
+   * existing ranges, the current endpoint is updated instead.
+   * 
+   * @param range
+   * @param addTo
+   */
+  static void addRange(int[] range, List<int[]> addTo)
+  {
+    /*
+     * list is empty - add to it!
+     */
+    if (addTo.size() == 0)
+    {
+      addTo.add(range);
+      return;
+    }
+
+    int[] last = addTo.get(addTo.size() - 1);
+    boolean lastForward = last[1] >= last[0];
+    boolean newForward = range[1] >= range[0];
+
+    /*
+     * contiguous range in the same direction - just update endpoint
+     */
+    if (lastForward == newForward && last[1] == range[0])
+    {
+      last[1] = range[1];
+      return;
+    }
+
+    /*
+     * next range starts at +1 in forward sense - update endpoint
+     */
+    if (lastForward && newForward && range[0] == last[1] + 1)
+    {
+      last[1] = range[1];
+      return;
+    }
+
+    /*
+     * next range starts at -1 in reverse sense - update endpoint
+     */
+    if (!lastForward && !newForward && range[0] == last[1] - 1)
+    {
+      last[1] = range[1];
+      return;
+    }
+
+    /*
+     * just add the new range
+     */
+    addTo.add(range);
+  }
+
+  /**
    * Returns true if mapping is from forward strand, false if from reverse
    * strand. Result is just based on the first 'from' range that is not a single
    * position. Default is true unless proven to be false. Behaviour is not well
@@ -1139,11 +1217,20 @@ public class MapList
     for (int[] range : getToRanges())
     {
       int[] transferred = map.locateInTo(range[0], range[1]);
-      if (transferred == null)
+      if (transferred == null || transferred.length % 2 != 0)
       {
         return null;
       }
-      toRanges.add(transferred);
+
+      /*
+       *  convert [start1, end1, start2, end2, ...] 
+       *  to [[start1, end1], [start2, end2], ...]
+       */
+      for (int i = 0; i < transferred.length;)
+      {
+        toRanges.add(new int[] { transferred[i], transferred[i + 1] });
+        i += 2;
+      }
     }
 
     return new MapList(getFromRanges(), toRanges, outFromRatio, outToRatio);