Merge branch 'develop' into task/JAL-3796_notarization
[jalview.git] / src / jalview / util / ShiftList.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.util;
22
23 import java.util.ArrayList;
24 import java.util.List;
25
26 /**
27  * ShiftList Simple way of mapping a linear series to a new linear range with
28  * new points introduced. Use at your own risk! Now growing to be used for
29  * interval ranges (position, offset) storing deletions/insertions
30  */
31 public class ShiftList
32 {
33   private List<int[]> shifts;
34
35   public ShiftList()
36   {
37     shifts = new ArrayList<int[]>();
38   }
39
40   /**
41    * addShift
42    * 
43    * @param pos
44    *          start position for shift (in original reference frame)
45    * @param shift
46    *          length of shift
47    */
48   public void addShift(int pos, int shift)
49   {
50     synchronized (shifts)
51     {
52       int sidx = 0;
53       int[] rshift = null;
54       while (sidx < shifts.size() && (rshift = shifts.get(sidx))[0] < pos)
55       {
56         sidx++;
57       }
58       if (sidx == shifts.size())
59       {
60         shifts.add(sidx, new int[] { pos, shift });
61       }
62       else
63       {
64         rshift[1] += shift;
65       }
66     }
67   }
68
69   /**
70    * shift
71    * 
72    * @param pos
73    *          int
74    * @return int shifted position
75    */
76   public int shift(int pos)
77   {
78     if (shifts.size() == 0)
79     {
80       return pos;
81     }
82     int shifted = pos;
83     int sidx = 0;
84     int rshift[];
85     while (sidx < shifts.size()
86             && (rshift = (shifts.get(sidx++)))[0] <= pos)
87     {
88       shifted += rshift[1];
89     }
90     return shifted;
91   }
92
93   /**
94    * clear all shifts
95    */
96   public synchronized void clear()
97   {
98     shifts.clear();
99   }
100
101   /**
102    * invert the shifts
103    * 
104    * @return ShiftList with inverse shift operations
105    */
106   public ShiftList getInverse()
107   {
108     ShiftList inverse = new ShiftList();
109     synchronized (shifts)
110     {
111       if (shifts != null)
112       {
113         for (int[] sh : shifts)
114         {
115           if (sh != null)
116           {
117             inverse.shifts.add(new int[] { sh[0], -sh[1] });
118           }
119         }
120       }
121     }
122     return inverse;
123   }
124
125   /**
126    * parse a 1d map of position 1&lt;i&lt;n to L&lt;pos[i]&lt;N such as that
127    * returned from SequenceI.gapMap()
128    * 
129    * @param gapMap
130    * @return shifts from map index to mapped position
131    */
132   public static ShiftList parseMap(int[] gapMap)
133   {
134     ShiftList shiftList = null;
135     if (gapMap != null && gapMap.length > 0)
136     {
137       shiftList = new ShiftList();
138       for (int i = 0, p = 0; i < gapMap.length; p++, i++)
139       {
140         if (p != gapMap[i])
141         {
142           shiftList.addShift(p, gapMap[i] - p);
143           p = gapMap[i];
144         }
145       }
146     }
147     return shiftList;
148   }
149
150   public List<int[]> getShifts()
151   {
152     return shifts;
153   }
154 }