JAL-1619 refactoring / tests to support 'align linked dna as protein'
[jalview.git] / src / jalview / datamodel / SearchResults.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
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
10  * of the License, or (at your option) any later version.
11  *  
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.
16  * 
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.
20  */
21 package jalview.datamodel;
22
23 import java.util.ArrayList;
24 import java.util.List;
25
26 public class SearchResults
27 {
28
29   private List<Match> matches = new ArrayList<Match>();
30
31   /**
32    * This method replaces the old search results which merely held an alignment
33    * index of search matches. This broke when sequences were moved around the
34    * alignment
35    * 
36    * @param seq
37    *          Sequence
38    * @param start
39    *          int
40    * @param end
41    *          int
42    */
43   public void addResult(SequenceI seq, int start, int end)
44   {
45     matches.add(new Match(seq, start, end));
46   }
47
48   /**
49    * Quickly check if the given sequence is referred to in the search results
50    * 
51    * @param sequence
52    *          (specific alignment sequence or a dataset sequence)
53    * @return true if the results involve sequence
54    */
55   public boolean involvesSequence(SequenceI sequence)
56   {
57     SequenceI ds = sequence.getDatasetSequence();
58     for (Match m : matches)
59     {
60       if (m.sequence != null
61               && (m.sequence == sequence || m.sequence == ds))
62       {
63         return true;
64       }
65     }
66     return false;
67   }
68
69   /**
70    * This Method returns the search matches which lie between the start and end
71    * points of the sequence in question. It is optimised for returning objects
72    * for drawing on SequenceCanvas
73    */
74   public int[] getResults(SequenceI sequence, int start, int end)
75   {
76     if (matches.isEmpty())
77     {
78       return null;
79     }
80
81     int[] result = null;
82     int[] tmp = null;
83     int resultLength, matchStart = 0, matchEnd = 0;
84     boolean mfound;
85     for (Match m : matches)
86     {
87       mfound = false;
88       if (m.sequence == sequence)
89       {
90         mfound = true;
91         // locate aligned position
92         matchStart = sequence.findIndex(m.start) - 1;
93         matchEnd = sequence.findIndex(m.end) - 1;
94       }
95       else if (m.sequence == sequence.getDatasetSequence())
96       {
97         mfound = true;
98         // locate region in local context
99         matchStart = sequence.findIndex(m.start) - 1;
100         matchEnd = sequence.findIndex(m.end) - 1;
101       }
102       if (mfound)
103       {
104         if (matchStart <= end && matchEnd >= start)
105         {
106           if (matchStart < start)
107           {
108             matchStart = start;
109           }
110
111           if (matchEnd > end)
112           {
113             matchEnd = end;
114           }
115
116           if (result == null)
117           {
118             result = new int[]
119             { matchStart, matchEnd };
120           }
121           else
122           {
123             resultLength = result.length;
124             tmp = new int[resultLength + 2];
125             System.arraycopy(result, 0, tmp, 0, resultLength);
126             result = tmp;
127             result[resultLength] = matchStart;
128             result[resultLength + 1] = matchEnd;
129           }
130         }
131         else
132         {
133           // debug
134           // System.err.println("Outwith bounds!" + matchStart+">"+end +"  or "
135           // + matchEnd+"<"+start);
136         }
137       }
138     }
139     return result;
140   }
141
142   public int getSize()
143   {
144     return matches.size();
145   }
146
147   public SequenceI getResultSequence(int index)
148   {
149     return matches.get(index).sequence;
150   }
151
152   public int getResultStart(int index)
153   {
154     return matches.get(index).start;
155   }
156
157   public int getResultEnd(int index)
158   {
159     return matches.get(index).end;
160   }
161
162   class Match
163   {
164     SequenceI sequence;
165
166     int start;
167
168     int end;
169
170     public Match(SequenceI seq, int start, int end)
171     {
172       sequence = seq;
173       this.start = start;
174       this.end = end;
175     }
176   }
177
178   /**
179    * Returns true if no search result matches are held.
180    * 
181    * @return
182    */
183   public boolean isEmpty()
184   {
185     return matches.isEmpty();
186   }
187 }