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