JAL-1432 updated copyright notices
[jalview.git] / src / jalview / analysis / Finder.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
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 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  * The Jalview Authors are detailed in the 'AUTHORS' file.
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 = -1;
48
49   public Finder(AlignmentI alignment, SequenceGroup selection)
50   {
51     this.alignment = alignment;
52     this.selection = selection;
53   }
54
55   /**
56    * restart search at given sequence and residue on alignment and (optionally)
57    * contained in selection
58    * 
59    * @param alignment
60    * @param selectionGroup
61    * @param seqIndex
62    * @param resIndex
63    */
64   public Finder(AlignmentI alignment, SequenceGroup selectionGroup,
65           int seqIndex, int resIndex)
66   {
67     this(alignment, selectionGroup);
68     this.seqIndex = seqIndex;
69     this.resIndex = resIndex;
70   }
71
72   public boolean find(String searchString)
73   {
74     boolean hasResults = false;
75     if (!caseSensitive)
76     {
77       searchString = searchString.toUpperCase();
78     }
79     regex = new com.stevesoft.pat.Regex(searchString);
80     regex.setIgnoreCase(!caseSensitive);
81     searchResults = new SearchResults();
82     idMatch = new Vector();
83     Sequence seq;
84     String item = null;
85     boolean found = false;
86     int end = alignment.getHeight();
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             {
128               found = true;
129               break;
130             }
131           }
132         } catch (NumberFormatException ex)
133         {
134         }
135
136         if (regex.search(seq.getName()))
137         {
138           idMatch.addElement(seq);
139           hasResults = true;
140           if (!findAll)
141           {
142             // stop and return the match
143             found = true;
144             break;
145           }
146         }
147       }
148       item = seq.getSequenceAsString();
149
150       if ((selection != null)
151               && (selection.getEndRes() < alignment.getWidth() - 1))
152       {
153         item = item.substring(0, selection.getEndRes() + 1);
154       }
155
156       // /Shall we ignore gaps???? - JBPNote: Add Flag for forcing this or not
157       StringBuffer noGapsSB = new StringBuffer();
158       int insertCount = 0;
159       Vector spaces = new Vector();
160
161       for (int j = 0; j < item.length(); j++)
162       {
163         if (!jalview.util.Comparison.isGap(item.charAt(j)))
164         {
165           noGapsSB.append(item.charAt(j));
166           spaces.addElement(new Integer(insertCount));
167         }
168         else
169         {
170           insertCount++;
171         }
172       }
173
174       String noGaps = noGapsSB.toString();
175
176       for (int r = resIndex; r < noGaps.length(); r++)
177       {
178
179         if (regex.searchFrom(noGaps, r))
180         {
181           resIndex = regex.matchedFrom();
182
183           if ((selection != null && selection.getSize() > 0)
184                   && ((resIndex + Integer.parseInt(spaces.elementAt(
185                           resIndex).toString())) < selection.getStartRes()))
186           {
187             continue;
188           }
189
190           int sres = seq
191                   .findPosition(resIndex
192                           + Integer.parseInt(spaces.elementAt(resIndex)
193                                   .toString()));
194           int eres = seq.findPosition(regex.matchedTo()
195                   - 1
196                   + Integer.parseInt(spaces
197                           .elementAt(regex.matchedTo() - 1).toString()));
198
199           searchResults.addResult(seq, sres, eres);
200           hasResults = true;
201           if (!findAll)
202           {
203             // thats enough, break and display the result
204             found = true;
205             resIndex++;
206
207             break;
208           }
209
210           r = resIndex;
211         }
212         else
213         {
214           break;
215         }
216       }
217
218       if (!found)
219       {
220         seqIndex++;
221         resIndex = -1;
222       }
223     }
224
225     /**
226      * We now search the Id string in the main search loop. for (int id = 0; id
227      * < alignment.getHeight(); id++) { if
228      * (regex.search(alignment.getSequenceAt(id).getName())) {
229      * idMatch.addElement(alignment.getSequenceAt(id)); hasResults = true; } }
230      */
231     return hasResults;
232   }
233
234   /**
235    * @return the alignment
236    */
237   public AlignmentI getAlignment()
238   {
239     return alignment;
240   }
241
242   /**
243    * @param alignment
244    *          the alignment to set
245    */
246   public void setAlignment(AlignmentI alignment)
247   {
248     this.alignment = alignment;
249   }
250
251   /**
252    * @return the caseSensitive
253    */
254   public boolean isCaseSensitive()
255   {
256     return caseSensitive;
257   }
258
259   /**
260    * @param caseSensitive
261    *          the caseSensitive to set
262    */
263   public void setCaseSensitive(boolean caseSensitive)
264   {
265     this.caseSensitive = caseSensitive;
266   }
267
268   /**
269    * @return the findAll
270    */
271   public boolean isFindAll()
272   {
273     return findAll;
274   }
275
276   /**
277    * @param findAll
278    *          the findAll to set
279    */
280   public void setFindAll(boolean findAll)
281   {
282     this.findAll = findAll;
283   }
284
285   /**
286    * @return the selection
287    */
288   public jalview.datamodel.SequenceGroup getSelection()
289   {
290     return selection;
291   }
292
293   /**
294    * @param selection
295    *          the selection to set
296    */
297   public void setSelection(jalview.datamodel.SequenceGroup selection)
298   {
299     this.selection = selection;
300   }
301
302   /**
303    * @return the idMatch
304    */
305   public Vector getIdMatch()
306   {
307     return idMatch;
308   }
309
310   /**
311    * @return the regex
312    */
313   public com.stevesoft.pat.Regex getRegex()
314   {
315     return regex;
316   }
317
318   /**
319    * @return the searchResults
320    */
321   public SearchResults getSearchResults()
322   {
323     return searchResults;
324   }
325
326   /**
327    * @return the resIndex
328    */
329   public int getResIndex()
330   {
331     return resIndex;
332   }
333
334   /**
335    * @param resIndex
336    *          the resIndex to set
337    */
338   public void setResIndex(int resIndex)
339   {
340     this.resIndex = resIndex;
341   }
342
343   /**
344    * @return the seqIndex
345    */
346   public int getSeqIndex()
347   {
348     return seqIndex;
349   }
350
351   /**
352    * @param seqIndex
353    *          the seqIndex to set
354    */
355   public void setSeqIndex(int seqIndex)
356   {
357     this.seqIndex = seqIndex;
358   }
359 }