+ if (includeDescription && searchSequenceDescription(seq, searchPattern))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Searches for a match with the sequence features, and if found, adds the
+ * sequence to the list of match ids, (but not as a duplicate). Answers true
+ * if a match was added, else false.
+ *
+ * @param seq
+ * @param searchPattern
+ * @return
+ */
+ protected boolean searchSequenceFeatures(int from, Regex searchPattern)
+ {
+ if (lastFeatureSequenceIndex != sequenceIndex)
+ {
+ lastFeatureSequenceIndex = sequenceIndex;
+ lastFeature = null;
+ }
+ SequenceI seq = viewport.getAlignment().getSequenceAt(sequenceIndex);
+ SequenceFeaturesI sf = seq.getFeatures();
+
+ // TODO - stash feature list and search incrementally
+ List<SequenceFeature> allFeatures = null;
+ if (frm != null)
+ {
+ allFeatures = frm.findFeaturesAtResidue(seq, seq.getStart(),
+ seq.getEnd());
+ }
+ else
+ {
+ allFeatures = sf.getAllFeatures(null);
+ }
+ // so we can check we are advancing when debugging
+ long fpos = 0;
+
+ for (SequenceFeature feature : allFeatures)
+ {
+ fpos++;
+ if (lastFeature != null)
+ {
+ // iterate till we find last feature matched
+ if (lastFeature != feature)
+ {
+ continue;
+ }
+ else
+ {
+ lastFeature = null;
+ continue;
+ }
+ }
+
+ if (searchPattern.search(feature.type) || (feature.description != null
+ && searchPattern.search(feature.description)))
+ {
+ searchResults.addResult(seq, feature.getBegin(), feature.getEnd());
+ lastFeature = feature;
+ return true;
+ }
+ }
+ residueIndex = Integer.MAX_VALUE;
+ lastFeature = null;
+ return false;
+ }
+
+ /**
+ * Searches for a match with the sequence description, and if found, adds the
+ * sequence to the list of match ids (but not as a duplicate). Answers true if
+ * a match was added, else false.
+ *
+ * @param seq
+ * @param searchPattern
+ * @return
+ */
+ protected boolean searchSequenceDescription(SequenceI seq,
+ Regex searchPattern)
+ {
+ String desc = seq.getDescription();
+ if (desc != null && searchPattern.search(desc)
+ && !idMatches.contains(seq))
+ {
+ idMatches.add(seq);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Searches for a match with the sequence name, and if found, adds the
+ * sequence to the list of match ids (but not as a duplicate). Answers true if
+ * a match was added, else false.
+ *
+ * @param seq
+ * @param searchPattern
+ * @return
+ */
+ protected boolean searchSequenceName(SequenceI seq, Regex searchPattern)
+ {
+ if (searchPattern.search(seq.getName()) && !idMatches.contains(seq))
+ {
+ idMatches.add(seq);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * If the residue position is valid for the sequence, and in a visible column,
+ * adds the position to the search results and returns true, else answers
+ * false.
+ *
+ * @param seq
+ * @param resNo
+ * @return
+ */
+ protected boolean searchForResidueNumber(SequenceI seq, int resNo)
+ {
+ if (seq.getStart() <= resNo && seq.getEnd() >= resNo)
+ {
+ if (isVisible(seq, resNo))
+ {
+ searchResults.addResult(seq, resNo, resNo);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if the residue is in a visible column, else false
+ *
+ * @param seq
+ * @param res
+ * @return
+ */
+ private boolean isVisible(SequenceI seq, int res)
+ {
+ if (!viewport.hasHiddenColumns())
+ {
+ return true;
+ }
+ int col = seq.findIndex(res); // base 1
+ return viewport.getAlignment().getHiddenColumns().isVisible(col - 1); // base
+ // 0
+ }
+
+ @Override
+ public List<SequenceI> getIdMatches()
+ {
+ return idMatches;
+ }
+
+ @Override
+ public SearchResultsI getSearchResults()
+ {
+ return searchResults;
+ }
+
+ @Override
+ public void setFeatureRenderer(FeatureRenderer featureRenderer)
+ {
+ frm = featureRenderer;
+ }