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