Jalview 2.6 source licence
[jalview.git] / src / jalview / analysis / Finder.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.6)
3  * Copyright (C) 2010 J Procter, AM Waterhouse, 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
86     // //// is the searchString a residue number?
87     try
88     {
89       int res = Integer.parseInt(searchString);
90       found = true;
91       if (selection == null || selection.getSize() < 1)
92       {
93         seq = (Sequence) alignment.getSequenceAt(0);
94       }
95       else
96       {
97         seq = (Sequence) (selection.getSequenceAt(0));
98       }
99
100       searchResults.addResult(seq, res, res);
101       hasResults = true;
102     } catch (NumberFormatException ex)
103     {
104     }
105
106     // /////////////////////////////////////////////
107
108     int end = alignment.getHeight();
109
110     if (selection != null)
111     {
112       if ((selection.getSize() < 1)
113               || ((selection.getEndRes() - selection.getStartRes()) < 2))
114       {
115         selection = null;
116       }
117     }
118
119     while (!found && (seqIndex < end))
120     {
121       seq = (Sequence) alignment.getSequenceAt(seqIndex);
122
123       if ((selection != null && selection.getSize() > 0)
124               && !selection.getSequences(null).contains(seq))
125       {
126         seqIndex++;
127         resIndex = -1;
128
129         continue;
130       }
131       if (resIndex < 0)
132       {
133         resIndex = 0;
134         if (regex.search(seq.getName()))
135         {
136           idMatch.addElement(seq);
137           hasResults = true;
138           if (!findAll)
139           {
140             // stop and return the match
141             found = true;
142             break;
143           }
144         }
145       }
146       item = seq.getSequenceAsString();
147
148       if ((selection != null)
149               && (selection.getEndRes() < alignment.getWidth() - 1))
150       {
151         item = item.substring(0, selection.getEndRes() + 1);
152       }
153
154       // /Shall we ignore gaps???? - JBPNote: Add Flag for forcing this or not
155       StringBuffer noGapsSB = new StringBuffer();
156       int insertCount = 0;
157       Vector spaces = new Vector();
158
159       for (int j = 0; j < item.length(); j++)
160       {
161         if (!jalview.util.Comparison.isGap(item.charAt(j)))
162         {
163           noGapsSB.append(item.charAt(j));
164           spaces.addElement(new Integer(insertCount));
165         }
166         else
167         {
168           insertCount++;
169         }
170       }
171
172       String noGaps = noGapsSB.toString();
173
174       for (int r = resIndex; r < noGaps.length(); r++)
175       {
176
177         if (regex.searchFrom(noGaps, r))
178         {
179           resIndex = regex.matchedFrom();
180
181           if ((selection != null && selection.getSize() > 0)
182                   && ((resIndex + Integer.parseInt(spaces.elementAt(
183                           resIndex).toString())) < selection.getStartRes()))
184           {
185             continue;
186           }
187
188           int sres = seq
189                   .findPosition(resIndex
190                           + Integer.parseInt(spaces.elementAt(resIndex)
191                                   .toString()));
192           int eres = seq.findPosition(regex.matchedTo()
193                   - 1
194                   + Integer.parseInt(spaces
195                           .elementAt(regex.matchedTo() - 1).toString()));
196
197           searchResults.addResult(seq, sres, eres);
198           hasResults = true;
199           if (!findAll)
200           {
201             // thats enough, break and display the result
202             found = true;
203             resIndex++;
204
205             break;
206           }
207
208           r = resIndex;
209         }
210         else
211         {
212           break;
213         }
214       }
215
216       if (!found)
217       {
218         seqIndex++;
219         resIndex = -1;
220       }
221     }
222
223     /**
224      * We now search the Id string in the main search loop. for (int id = 0; id
225      * < alignment.getHeight(); id++) { if
226      * (regex.search(alignment.getSequenceAt(id).getName())) {
227      * idMatch.addElement(alignment.getSequenceAt(id)); hasResults = true; } }
228      */
229     return hasResults;
230   }
231
232   /**
233    * @return the alignment
234    */
235   public AlignmentI getAlignment()
236   {
237     return alignment;
238   }
239
240   /**
241    * @param alignment
242    *          the alignment to set
243    */
244   public void setAlignment(AlignmentI alignment)
245   {
246     this.alignment = alignment;
247   }
248
249   /**
250    * @return the caseSensitive
251    */
252   public boolean isCaseSensitive()
253   {
254     return caseSensitive;
255   }
256
257   /**
258    * @param caseSensitive
259    *          the caseSensitive to set
260    */
261   public void setCaseSensitive(boolean caseSensitive)
262   {
263     this.caseSensitive = caseSensitive;
264   }
265
266   /**
267    * @return the findAll
268    */
269   public boolean isFindAll()
270   {
271     return findAll;
272   }
273
274   /**
275    * @param findAll
276    *          the findAll to set
277    */
278   public void setFindAll(boolean findAll)
279   {
280     this.findAll = findAll;
281   }
282
283   /**
284    * @return the selection
285    */
286   public jalview.datamodel.SequenceGroup getSelection()
287   {
288     return selection;
289   }
290
291   /**
292    * @param selection
293    *          the selection to set
294    */
295   public void setSelection(jalview.datamodel.SequenceGroup selection)
296   {
297     this.selection = selection;
298   }
299
300   /**
301    * @return the idMatch
302    */
303   public Vector getIdMatch()
304   {
305     return idMatch;
306   }
307
308   /**
309    * @return the regex
310    */
311   public com.stevesoft.pat.Regex getRegex()
312   {
313     return regex;
314   }
315
316   /**
317    * @return the searchResults
318    */
319   public SearchResults getSearchResults()
320   {
321     return searchResults;
322   }
323
324   /**
325    * @return the resIndex
326    */
327   public int getResIndex()
328   {
329     return resIndex;
330   }
331
332   /**
333    * @param resIndex
334    *          the resIndex to set
335    */
336   public void setResIndex(int resIndex)
337   {
338     this.resIndex = resIndex;
339   }
340
341   /**
342    * @return the seqIndex
343    */
344   public int getSeqIndex()
345   {
346     return seqIndex;
347   }
348
349   /**
350    * @param seqIndex
351    *          the seqIndex to set
352    */
353   public void setSeqIndex(int seqIndex)
354   {
355     this.seqIndex = seqIndex;
356   }
357 }