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