+ // TODO not used - remove??
+ int[] mp = shiftTo(mpos);
+ if (mp != null)
+ {
+ return mp[0];
+ }
+ return mpos;
+ }
+
+ /**
+ * get range of positions in To frame for the mpos word in From
+ *
+ * @param mpos
+ * position in From
+ * @return null or int[] first position in To for mpos, last position in to
+ * for Mpos
+ */
+ public int[] getToWord(int mpos)
+ {
+ int[] mp = shiftTo(mpos);
+ if (mp != null)
+ {
+ return new int[] { mp[0], mp[0] + mp[2] * (getFromRatio() - 1) };
+ }
+ return null;
+ }
+
+ /**
+ * get From position in the associated reference frame for position pos in the
+ * associated sequence.
+ *
+ * @param pos
+ * @return
+ */
+ public int getMappedPosition(int pos)
+ {
+ // TODO not used - remove??
+ int[] mp = shiftFrom(pos);
+ if (mp != null)
+ {
+ return mp[0];
+ }
+ return pos;
+ }
+
+ public int[] getMappedWord(int pos)
+ {
+ // TODO not used - remove??
+ int[] mp = shiftFrom(pos);
+ if (mp != null)
+ {
+ return new int[] { mp[0], mp[0] + mp[2] * (getToRatio() - 1) };
+ }
+ return null;
+ }
+
+ /**
+ *
+ * @return a MapList whose From range is this maplist's To Range, and vice
+ * versa
+ */
+ public MapList getInverse()
+ {
+ return new MapList(getToRanges(), getFromRanges(), getToRatio(),
+ getFromRatio());
+ }
+
+ /**
+ * test for containment rather than equivalence to another mapping
+ *
+ * @param map
+ * to be tested for containment
+ * @return true if local or mapped range map contains or is contained by this
+ * mapping
+ */
+ public boolean containsEither(boolean local, MapList map)
+ {
+ // TODO not used - remove?
+ if (local)
+ {
+ return ((getFromLowest() >= map.getFromLowest() && getFromHighest() <= map
+ .getFromHighest()) || (getFromLowest() <= map.getFromLowest() && getFromHighest() >= map
+ .getFromHighest()));
+ }
+ else
+ {
+ return ((getToLowest() >= map.getToLowest() && getToHighest() <= map
+ .getToHighest()) || (getToLowest() <= map.getToLowest() && getToHighest() >= map
+ .getToHighest()));
+ }
+ }
+
+ /**
+ * String representation - for debugging, not guaranteed not to change
+ */
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder(64);
+ sb.append("[");
+ for (int[] shift : fromShifts)
+ {
+ sb.append(" ").append(Arrays.toString(shift));
+ }
+ sb.append(" ] ");
+ sb.append(fromRatio).append(":").append(toRatio);
+ sb.append(" to [");
+ for (int[] shift : toShifts)
+ {
+ sb.append(" ").append(Arrays.toString(shift));
+ }
+ sb.append(" ]");
+ return sb.toString();
+ }
+
+ /**
+ * Extend this map list by adding the given map's ranges. There is no
+ * validation check that the ranges do not overlap existing ranges (or each
+ * other), but contiguous ranges are merged.
+ *
+ * @param map
+ */
+ public void addMapList(MapList map)
+ {
+ if (this.equals(map))
+ {
+ return;
+ }
+ this.fromLowest = Math.min(fromLowest, map.fromLowest);
+ this.toLowest = Math.min(toLowest, map.toLowest);
+ this.fromHighest = Math.max(fromHighest, map.fromHighest);
+ this.toHighest = Math.max(toHighest, map.toHighest);
+
+ for (int[] range : map.getFromRanges())
+ {
+ addRange(range, fromShifts);
+ }
+ for (int[] range : map.getToRanges())
+ {
+ 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;
+ }