2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.analysis;
23 import jalview.datamodel.AlignmentI;
24 import jalview.datamodel.SearchResultMatchI;
25 import jalview.datamodel.SearchResults;
26 import jalview.datamodel.SearchResultsI;
27 import jalview.datamodel.SequenceGroup;
28 import jalview.datamodel.SequenceI;
29 import jalview.util.Comparison;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.Vector;
35 import com.stevesoft.pat.Regex;
40 * Implements the search algorithms for the Find dialog box.
42 SearchResultsI searchResults;
46 SequenceGroup selection = null;
48 Vector<SequenceI> idMatch = null;
50 boolean caseSensitive = false;
52 private boolean includeDescription = false;
54 boolean findAll = false;
59 * holds last-searched position between calls to find(false)
61 int seqIndex = 0, resIndex = -1;
63 public Finder(AlignmentI alignment, SequenceGroup selection)
65 this.alignment = alignment;
66 this.selection = selection;
70 * restart search at given sequence and residue on alignment and (optionally)
71 * contained in selection
74 * @param selectionGroup
78 public Finder(AlignmentI alignment, SequenceGroup selectionGroup,
79 int seqIndex, int resIndex)
81 this(alignment, selectionGroup);
82 this.seqIndex = seqIndex;
83 this.resIndex = resIndex;
86 public boolean find(String searchString)
88 boolean hasResults = false;
91 searchString = searchString.toUpperCase();
93 regex = new Regex(searchString);
94 regex.setIgnoreCase(!caseSensitive);
95 searchResults = new SearchResults();
96 idMatch = new Vector<SequenceI>();
98 boolean found = false;
99 int end = alignment.getHeight();
101 // /////////////////////////////////////////////
103 if (selection != null)
105 if ((selection.getSize() < 1)
106 || ((selection.getEndRes() - selection.getStartRes()) < 2))
111 SearchResultMatchI lastm = null;
113 while (!found && (seqIndex < end))
115 SequenceI seq = alignment.getSequenceAt(seqIndex);
117 if ((selection != null && selection.getSize() > 0)
118 && !selection.getSequences(null).contains(seq))
128 // test for one off matches - sequence position and sequence ID
129 // //// is the searchString a residue number?
132 int res = Integer.parseInt(searchString);
133 // possibly a residue number - check if valid for seq
134 if (seq.getEnd() >= res)
136 searchResults.addResult(seq, res, res);
138 // resIndex=seq.getLength();
146 } catch (NumberFormatException ex)
150 if (regex.search(seq.getName()) && !idMatch.contains(seq))
152 idMatch.addElement(seq);
156 // stop and return the match
162 if (isIncludeDescription() && seq.getDescription() != null
163 && regex.search(seq.getDescription())
164 && !idMatch.contains(seq))
166 idMatch.addElement(seq);
170 // stop and return the match
176 item = seq.getSequenceAsString();
178 if ((selection != null)
179 && (selection.getEndRes() < alignment.getWidth() - 1))
181 item = item.substring(0, selection.getEndRes() + 1);
184 // /Shall we ignore gaps???? - JBPNote: Add Flag for forcing this or not
185 StringBuilder noGapsSB = new StringBuilder();
187 List<Integer> spaces = new ArrayList<Integer>();
189 for (int j = 0; j < item.length(); j++)
191 if (!Comparison.isGap(item.charAt(j)))
193 noGapsSB.append(item.charAt(j));
194 spaces.add(Integer.valueOf(insertCount));
202 String noGaps = noGapsSB.toString();
203 for (int r = resIndex; r < noGaps.length(); r++)
206 if (regex.searchFrom(noGaps, r))
208 resIndex = regex.matchedFrom();
210 if ((selection != null && selection.getSize() > 0) && (resIndex
211 + spaces.get(resIndex) < selection.getStartRes()))
215 // if invalid string used, then regex has no matched to/from
216 int sres = seq.findPosition(resIndex + spaces.get(resIndex));
217 int eres = seq.findPosition(regex.matchedTo() - 1
218 + (spaces.get(regex.matchedTo() - 1)));
219 // only add result if not contained in previous result
220 if (lastm == null || (lastm.getSequence() != seq
221 || (!(lastm.getStart() <= sres
222 && lastm.getEnd() >= eres))))
224 lastm = searchResults.addResult(seq, sres, eres);
229 // thats enough, break and display the result
252 * We now search the Id string in the main search loop. for (int id = 0; id
253 * < alignment.getHeight(); id++) { if
254 * (regex.search(alignment.getSequenceAt(id).getName())) {
255 * idMatch.addElement(alignment.getSequenceAt(id)); hasResults = true; } }
261 * @return the alignment
263 public AlignmentI getAlignment()
270 * the alignment to set
272 public void setAlignment(AlignmentI alignment)
274 this.alignment = alignment;
278 * @return the caseSensitive
280 public boolean isCaseSensitive()
282 return caseSensitive;
286 * @param caseSensitive
287 * the caseSensitive to set
289 public void setCaseSensitive(boolean caseSensitive)
291 this.caseSensitive = caseSensitive;
295 * @return the findAll
297 public boolean isFindAll()
306 public void setFindAll(boolean findAll)
308 this.findAll = findAll;
312 * @return the selection
314 public jalview.datamodel.SequenceGroup getSelection()
321 * the selection to set
323 public void setSelection(jalview.datamodel.SequenceGroup selection)
325 this.selection = selection;
329 * Returns the (possibly empty) list of matching sequences (when search
330 * includes searching sequence names)
334 public Vector<SequenceI> getIdMatch()
342 public com.stevesoft.pat.Regex getRegex()
348 * @return the searchResults
350 public SearchResultsI getSearchResults()
352 return searchResults;
356 * @return the resIndex
358 public int getResIndex()
365 * the resIndex to set
367 public void setResIndex(int resIndex)
369 this.resIndex = resIndex;
373 * @return the seqIndex
375 public int getSeqIndex()
382 * the seqIndex to set
384 public void setSeqIndex(int seqIndex)
386 this.seqIndex = seqIndex;
389 public boolean isIncludeDescription()
391 return includeDescription;
394 public void setIncludeDescription(boolean includeDescription)
396 this.includeDescription = includeDescription;