JAL-1620 version bump and release notes
[jalview.git] / src / jalview / analysis / Finder.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2b1)
3  * Copyright (C) 2014 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.analysis;
22
23 import java.util.*;
24
25 import jalview.datamodel.*;
26
27 public class Finder
28 {
29   /**
30    * Implements the search algorithms for the Find dialog box.
31    */
32   SearchResults searchResults;
33
34   AlignmentI alignment;
35
36   jalview.datamodel.SequenceGroup selection = null;
37
38   Vector idMatch = null;
39
40   boolean caseSensitive = false;
41
42   boolean findAll = false;
43
44   com.stevesoft.pat.Regex regex = null;
45
46   /**
47    * hold's last-searched position between calles to find(false)
48    */
49   int seqIndex = 0, resIndex = -1;
50
51   public Finder(AlignmentI alignment, SequenceGroup selection)
52   {
53     this.alignment = alignment;
54     this.selection = selection;
55   }
56
57   /**
58    * restart search at given sequence and residue on alignment and (optionally)
59    * contained in selection
60    * 
61    * @param alignment
62    * @param selectionGroup
63    * @param seqIndex
64    * @param resIndex
65    */
66   public Finder(AlignmentI alignment, SequenceGroup selectionGroup,
67           int seqIndex, int resIndex)
68   {
69     this(alignment, selectionGroup);
70     this.seqIndex = seqIndex;
71     this.resIndex = resIndex;
72   }
73
74   public boolean find(String searchString)
75   {
76     boolean hasResults = false;
77     if (!caseSensitive)
78     {
79       searchString = searchString.toUpperCase();
80     }
81     regex = new com.stevesoft.pat.Regex(searchString);
82     regex.setIgnoreCase(!caseSensitive);
83     searchResults = new SearchResults();
84     idMatch = new Vector();
85     Sequence seq;
86     String item = null;
87     boolean found = false;
88     int end = alignment.getHeight();
89
90     // /////////////////////////////////////////////
91
92     if (selection != null)
93     {
94       if ((selection.getSize() < 1)
95               || ((selection.getEndRes() - selection.getStartRes()) < 2))
96       {
97         selection = null;
98       }
99     }
100
101     while (!found && (seqIndex < end))
102     {
103       seq = (Sequence) alignment.getSequenceAt(seqIndex);
104
105       if ((selection != null && selection.getSize() > 0)
106               && !selection.getSequences(null).contains(seq))
107       {
108         seqIndex++;
109         resIndex = -1;
110
111         continue;
112       }
113       if (resIndex < 0)
114       {
115         resIndex = 0;
116         // test for one off matches - sequence position and sequence ID
117         // //// is the searchString a residue number?
118         try
119         {
120           int res = Integer.parseInt(searchString);
121           // possibly a residue number - check if valid for seq
122           if (seq.getEnd() >= res)
123           {
124             searchResults.addResult(seq, res, res);
125             hasResults = true;
126             // resIndex=seq.getLength();
127             // seqIndex++;
128             if (!findAll)
129             {
130               found = true;
131               break;
132             }
133           }
134         } catch (NumberFormatException ex)
135         {
136         }
137
138         if (regex.search(seq.getName()))
139         {
140           idMatch.addElement(seq);
141           hasResults = true;
142           if (!findAll)
143           {
144             // stop and return the match
145             found = true;
146             break;
147           }
148         }
149       }
150       item = seq.getSequenceAsString();
151
152       if ((selection != null)
153               && (selection.getEndRes() < alignment.getWidth() - 1))
154       {
155         item = item.substring(0, selection.getEndRes() + 1);
156       }
157
158       // /Shall we ignore gaps???? - JBPNote: Add Flag for forcing this or not
159       StringBuffer noGapsSB = new StringBuffer();
160       int insertCount = 0;
161       Vector spaces = new Vector();
162
163       for (int j = 0; j < item.length(); j++)
164       {
165         if (!jalview.util.Comparison.isGap(item.charAt(j)))
166         {
167           noGapsSB.append(item.charAt(j));
168           spaces.addElement(new Integer(insertCount));
169         }
170         else
171         {
172           insertCount++;
173         }
174       }
175
176       String noGaps = noGapsSB.toString();
177
178       for (int r = resIndex; r < noGaps.length(); r++)
179       {
180
181         if (regex.searchFrom(noGaps, r))
182         {
183           resIndex = regex.matchedFrom();
184
185           if ((selection != null && selection.getSize() > 0)
186                   && ((resIndex + Integer.parseInt(spaces.elementAt(
187                           resIndex).toString())) < selection.getStartRes()))
188           {
189             continue;
190           }
191
192           int sres = seq
193                   .findPosition(resIndex
194                           + Integer.parseInt(spaces.elementAt(resIndex)
195                                   .toString()));
196           int eres = seq.findPosition(regex.matchedTo()
197                   - 1
198                   + Integer.parseInt(spaces
199                           .elementAt(regex.matchedTo() - 1).toString()));
200
201           searchResults.addResult(seq, sres, eres);
202           hasResults = true;
203           if (!findAll)
204           {
205             // thats enough, break and display the result
206             found = true;
207             resIndex++;
208
209             break;
210           }
211
212           r = resIndex;
213         }
214         else
215         {
216           break;
217         }
218       }
219
220       if (!found)
221       {
222         seqIndex++;
223         resIndex = -1;
224       }
225     }
226
227     /**
228      * We now search the Id string in the main search loop. for (int id = 0; id
229      * < alignment.getHeight(); id++) { if
230      * (regex.search(alignment.getSequenceAt(id).getName())) {
231      * idMatch.addElement(alignment.getSequenceAt(id)); hasResults = true; } }
232      */
233     return hasResults;
234   }
235
236   /**
237    * @return the alignment
238    */
239   public AlignmentI getAlignment()
240   {
241     return alignment;
242   }
243
244   /**
245    * @param alignment
246    *          the alignment to set
247    */
248   public void setAlignment(AlignmentI alignment)
249   {
250     this.alignment = alignment;
251   }
252
253   /**
254    * @return the caseSensitive
255    */
256   public boolean isCaseSensitive()
257   {
258     return caseSensitive;
259   }
260
261   /**
262    * @param caseSensitive
263    *          the caseSensitive to set
264    */
265   public void setCaseSensitive(boolean caseSensitive)
266   {
267     this.caseSensitive = caseSensitive;
268   }
269
270   /**
271    * @return the findAll
272    */
273   public boolean isFindAll()
274   {
275     return findAll;
276   }
277
278   /**
279    * @param findAll
280    *          the findAll to set
281    */
282   public void setFindAll(boolean findAll)
283   {
284     this.findAll = findAll;
285   }
286
287   /**
288    * @return the selection
289    */
290   public jalview.datamodel.SequenceGroup getSelection()
291   {
292     return selection;
293   }
294
295   /**
296    * @param selection
297    *          the selection to set
298    */
299   public void setSelection(jalview.datamodel.SequenceGroup selection)
300   {
301     this.selection = selection;
302   }
303
304   /**
305    * @return the idMatch
306    */
307   public Vector getIdMatch()
308   {
309     return idMatch;
310   }
311
312   /**
313    * @return the regex
314    */
315   public com.stevesoft.pat.Regex getRegex()
316   {
317     return regex;
318   }
319
320   /**
321    * @return the searchResults
322    */
323   public SearchResults getSearchResults()
324   {
325     return searchResults;
326   }
327
328   /**
329    * @return the resIndex
330    */
331   public int getResIndex()
332   {
333     return resIndex;
334   }
335
336   /**
337    * @param resIndex
338    *          the resIndex to set
339    */
340   public void setResIndex(int resIndex)
341   {
342     this.resIndex = resIndex;
343   }
344
345   /**
346    * @return the seqIndex
347    */
348   public int getSeqIndex()
349   {
350     return seqIndex;
351   }
352
353   /**
354    * @param seqIndex
355    *          the seqIndex to set
356    */
357   public void setSeqIndex(int seqIndex)
358   {
359     this.seqIndex = seqIndex;
360   }
361 }