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