Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
DBRefEntry | 31 | 70 | 70 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ 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.Locale; | |
24 | ||
25 | import jalview.api.DBRefEntryI; | |
26 | import jalview.util.DBRefUtils; | |
27 | import jalview.util.MapList; | |
28 | ||
29 | import java.util.List; | |
30 | ||
31 | public class DBRefEntry implements DBRefEntryI | |
32 | { | |
33 | String source = ""; | |
34 | ||
35 | private String version = ""; | |
36 | ||
37 | private String ucversion; | |
38 | ||
39 | private String accessionId = ""; | |
40 | ||
41 | int sourceKey = Integer.MIN_VALUE; | |
42 | ||
43 | String canonicalSourceName; | |
44 | ||
45 | boolean isCanonicalAccession = false; | |
46 | ||
47 | /* | |
48 | * maps from associated sequence to the database sequence's coordinate system | |
49 | */ | |
50 | Mapping map = null; | |
51 | ||
52 | 384 | public DBRefEntry() |
53 | { | |
54 | ||
55 | } | |
56 | ||
57 | /** | |
58 | * | |
59 | * @param source | |
60 | * may not be null | |
61 | * @param version | |
62 | * may be null | |
63 | * @param accessionId | |
64 | * may be null | |
65 | */ | |
66 | 3004 | public DBRefEntry(String source, String version, String accessionId) |
67 | { | |
68 | 3004 | this(source, version, accessionId, null, false); |
69 | } | |
70 | ||
71 | /** | |
72 | * | |
73 | * @param source | |
74 | * may not be null | |
75 | * @param version | |
76 | * may be null | |
77 | * @param accessionId | |
78 | * may be null | |
79 | */ | |
80 | 118 | public DBRefEntry(String source, String version, String accessionId, |
81 | Mapping map) | |
82 | { | |
83 | 118 | this(source, version, accessionId, map, false); |
84 | } | |
85 | ||
86 | /** | |
87 | * | |
88 | * @param source | |
89 | * canonical source (turned to uppercase; cannot be null) | |
90 | * @param version | |
91 | * (source dependent version string or null) | |
92 | * @param accessionId | |
93 | * (source dependent accession number string or null) | |
94 | * @param map | |
95 | * (mapping from local sequence numbering to source accession | |
96 | * numbering or null) | |
97 | */ | |
98 | 3215 | public DBRefEntry(String source, String version, String accessionId, |
99 | Mapping map, boolean isCanonical) | |
100 | { | |
101 | ||
102 | 3215 | this.source = source.toUpperCase(Locale.ROOT); |
103 | 3215 | setVersion(version); |
104 | 3215 | this.accessionId = accessionId; |
105 | 3215 | this.map = map; |
106 | 3215 | this.isCanonicalAccession = isCanonical; |
107 | } | |
108 | ||
109 | /** | |
110 | * Clone an entry, this time not allowing any null fields except map. | |
111 | * | |
112 | */ | |
113 | 22 | public DBRefEntry(DBRefEntryI entry) |
114 | { | |
115 | 22 | this((entry.getSource() == null ? "" : new String(entry.getSource())), |
116 | 22 | (entry.getVersion() == null ? "" |
117 | : new String(entry.getVersion())), | |
118 | 22 | (entry.getAccessionId() == null ? "" |
119 | : new String(entry.getAccessionId())), | |
120 | 22 | (entry.getMap() == null ? null : new Mapping(entry.getMap())), |
121 | entry.isCanonical()); | |
122 | } | |
123 | ||
124 | 80 | @Override |
125 | public boolean equals(Object o) | |
126 | { | |
127 | // TODO should also override hashCode to ensure equal objects have equal | |
128 | // hashcodes | |
129 | ||
130 | // if (o == null || !(o instanceof DBRefEntry)) | |
131 | // { | |
132 | // return false; | |
133 | // } | |
134 | // DBRefEntry entry = (DBRefEntry) o; | |
135 | // if (entry == this) | |
136 | // { | |
137 | // return true; | |
138 | // } | |
139 | 80 | Mapping em; |
140 | 80 | return (o != null && o instanceof DBRefEntry && (o == this || equalRef( |
141 | (DBRefEntry) o) | |
142 | && (map == null) == ((em = ((DBRefEntry) o).map) == null) | |
143 | && (map == null || map.equals(em)))); | |
144 | // | |
145 | // { | |
146 | // return true; | |
147 | // } | |
148 | // return false; | |
149 | } | |
150 | ||
151 | /** | |
152 | * Answers true if this object is either equivalent to, or can be 'improved' | |
153 | * by, the given entry. Specifically, answers true if | |
154 | * <ul> | |
155 | * <li>source and accession are identical (ignoring case)</li> | |
156 | * <li>version is identical (ignoring case), or this version is of the format | |
157 | * "someSource:0", in which case the version for the other entry replaces | |
158 | * it</li> | |
159 | * <li>mappings are not compared but if this entry has no mapping, replace | |
160 | * with that for the other entry</li> | |
161 | * </ul> | |
162 | * | |
163 | * @param other | |
164 | * @return | |
165 | */ | |
166 | 68295 | @Override |
167 | public boolean updateFrom(DBRefEntryI other) | |
168 | { | |
169 | 68295 | if (other == null) |
170 | { | |
171 | 1 | return false; |
172 | } | |
173 | 68294 | if (other == this) |
174 | { | |
175 | 1 | return true; |
176 | } | |
177 | ||
178 | 68293 | boolean improved = false; |
179 | /* | |
180 | * source must either match or be both null | |
181 | */ | |
182 | 68293 | String otherSource = other.getSource(); |
183 | 68293 | if ((source == null && otherSource != null) |
184 | || (source != null && otherSource == null) | |
185 | || (source != null && !source.equalsIgnoreCase(otherSource))) | |
186 | { | |
187 | 56124 | return false; |
188 | } | |
189 | ||
190 | /* | |
191 | * accession id must either match or be both null | |
192 | */ | |
193 | 12169 | String otherAccession = other.getAccessionId(); |
194 | 12169 | if ((accessionId == null && otherAccession != null) |
195 | || (accessionId != null && otherAccession == null) | |
196 | || (accessionId != null | |
197 | && !accessionId.equalsIgnoreCase(otherAccession))) | |
198 | { | |
199 | 12118 | return false; |
200 | } | |
201 | ||
202 | 51 | if (!isCanonicalAccession && other.isCanonical()) |
203 | { | |
204 | 2 | isCanonicalAccession = true; |
205 | 2 | improved = true; |
206 | } | |
207 | else | |
208 | { | |
209 | 49 | if (isCanonicalAccession && !other.isCanonical()) |
210 | { | |
211 | // other is not an authoritative source of canonical accessions | |
212 | 3 | return false; |
213 | } | |
214 | } | |
215 | /* | |
216 | * if my version is null, "0" or "source:0" then replace with other version, | |
217 | * otherwise the versions have to match | |
218 | */ | |
219 | 48 | String otherVersion = other.getVersion(); |
220 | ||
221 | 48 | if ((version == null || version.equals("0") || version.endsWith(":0")) |
222 | && otherVersion != null) | |
223 | { | |
224 | 13 | setVersion(otherVersion); |
225 | } | |
226 | else | |
227 | { | |
228 | 35 | if (version != null && (otherVersion == null |
229 | || !version.equalsIgnoreCase(otherVersion))) | |
230 | { | |
231 | // FIXME: there may be a problem with old version strings not allowing | |
232 | // updating of dbrefentries | |
233 | 4 | return improved; |
234 | } | |
235 | } | |
236 | ||
237 | /* | |
238 | * if I have no mapping, take that of the other dbref | |
239 | * - providing it had a version and so do I | |
240 | */ | |
241 | 44 | if (map == null) |
242 | { | |
243 | 40 | setMap(other.getMap()); |
244 | } | |
245 | 44 | return true; |
246 | } | |
247 | ||
248 | /** | |
249 | * test for similar DBRef attributes, except for the map object. | |
250 | * | |
251 | * @param entry | |
252 | * @return true if source, accession and version are equal with those of entry | |
253 | */ | |
254 | 82 | @Override |
255 | public boolean equalRef(DBRefEntryI entry) | |
256 | { | |
257 | // TODO is this method and equals() not needed? | |
258 | 82 | if (entry == null) |
259 | { | |
260 | 1 | return false; |
261 | } | |
262 | 81 | if (entry == this) |
263 | { | |
264 | 1 | return true; |
265 | } | |
266 | ||
267 | // BH 2019.01.25/2019.02.04 source cannot/should not be null. | |
268 | // for example, StructureChooser has dbRef.getSource().equalsIgnoreCase... | |
269 | ||
270 | 80 | return (entry != null |
271 | && (source != null && entry.getSource() != null | |
272 | && source.equalsIgnoreCase(entry.getSource())) | |
273 | && (accessionId != null && entry.getAccessionId() != null | |
274 | && accessionId.equalsIgnoreCase(entry.getAccessionId())) | |
275 | && (version != null && entry.getVersion() != null | |
276 | && version.equalsIgnoreCase(entry.getVersion()))); | |
277 | } | |
278 | ||
279 | 501052 | @Override |
280 | public String getSource() | |
281 | { | |
282 | 501052 | return source; |
283 | } | |
284 | ||
285 | 325 | public int getSourceKey() |
286 | { | |
287 | 325 | return (sourceKey == Integer.MIN_VALUE |
288 | ? (sourceKey = DBRefSource | |
289 | .getSourceKey(getCanonicalSourceName())) | |
290 | : sourceKey); | |
291 | } | |
292 | ||
293 | /** | |
294 | * can be null | |
295 | */ | |
296 | 484 | @Override |
297 | public String getVersion() | |
298 | { | |
299 | 484 | return version; |
300 | } | |
301 | ||
302 | /** | |
303 | * can be null | |
304 | */ | |
305 | 49941 | @Override |
306 | public String getAccessionId() | |
307 | { | |
308 | 49941 | return accessionId; |
309 | } | |
310 | ||
311 | 386 | @Override |
312 | public void setAccessionId(String accessionId) | |
313 | { | |
314 | 386 | this.accessionId = accessionId; |
315 | // this.accessionId = (accessionId == null ? "" : | |
316 | // accessionId).toUpperCase(Locale.ROOT); | |
317 | } | |
318 | ||
319 | /** | |
320 | * CAUTION! allows setting source null or not uppercase! | |
321 | */ | |
322 | 309 | @Override |
323 | public void setSource(String source) | |
324 | { | |
325 | 309 | this.source = source; |
326 | ||
327 | // this.source = (source == null ? "" : source).toUpperCase(Locale.ROOT); | |
328 | // this.canonicalSourceName = DBRefUtils.getCanonicalName(this.source); | |
329 | // this.sourceKey = DBRefSource.getSourceKey(this.canonicalSourceName); | |
330 | } | |
331 | ||
332 | 3549 | @Override |
333 | public void setVersion(String version) | |
334 | { | |
335 | 3549 | this.version = version; |
336 | 3549 | this.ucversion = (version == null ? null |
337 | : version.toUpperCase(Locale.ROOT)); | |
338 | } | |
339 | ||
340 | 2488 | @Override |
341 | public Mapping getMap() | |
342 | { | |
343 | 2488 | return map; |
344 | } | |
345 | ||
346 | /** | |
347 | * @param map | |
348 | * the map to set | |
349 | */ | |
350 | 207 | public void setMap(Mapping map) |
351 | { | |
352 | 207 | this.map = map; |
353 | } | |
354 | ||
355 | 641 | public boolean hasMap() |
356 | { | |
357 | 641 | return map != null; |
358 | } | |
359 | ||
360 | /** | |
361 | * | |
362 | * @return source+":"+accessionId | |
363 | */ | |
364 | 7 | public String getSrcAccString() |
365 | { | |
366 | 7 | return ((source != null) ? source : "") + ":" |
367 | 7 | + ((accessionId != null) ? accessionId : ""); |
368 | } | |
369 | ||
370 | 7 | @Override |
371 | public String toString() | |
372 | { | |
373 | 7 | return getSrcAccString(); |
374 | } | |
375 | ||
376 | 880 | @Override |
377 | public boolean isPrimaryCandidate() | |
378 | { | |
379 | /* | |
380 | * if a map is present, unless it is 1:1 and has no SequenceI mate, it cannot be a primary reference. | |
381 | */ | |
382 | 880 | if (map != null) |
383 | { | |
384 | 51 | SequenceI mto = map.getTo(); |
385 | 51 | if (mto != null) |
386 | { | |
387 | 25 | return false; |
388 | } | |
389 | 26 | MapList ml = map.getMap(); |
390 | 26 | if (ml.getFromRatio() != ml.getToRatio() || ml.getFromRatio() != 1) |
391 | { | |
392 | 4 | return false; |
393 | } | |
394 | // check map is between identical single contiguous ranges | |
395 | 22 | List<int[]> fromRanges, toRanges; |
396 | ? | if ((fromRanges = ml.getFromRanges()).size() != 1 |
397 | || (toRanges = ml.getToRanges()).size() != 1) | |
398 | { | |
399 | 13 | return false; |
400 | } | |
401 | 9 | if (fromRanges.get(0)[0] != toRanges.get(0)[0] |
402 | || fromRanges.get(0)[1] != toRanges.get(0)[1]) | |
403 | { | |
404 | 3 | return false; |
405 | } | |
406 | } | |
407 | 835 | if (version == null) |
408 | { | |
409 | // no version string implies the reference has not been verified at all. | |
410 | 1 | return false; |
411 | } | |
412 | ||
413 | 834 | return DBRefSource.isPrimaryCandidate(ucversion); |
414 | } | |
415 | ||
416 | /** | |
417 | * stores the upper-case canonical name of the source for use in | |
418 | * Sequence.getPrimaryDBRefs(). | |
419 | * | |
420 | * @author Bob Hanson | |
421 | * | |
422 | * @return | |
423 | */ | |
424 | 358 | public String getCanonicalSourceName() |
425 | { | |
426 | 358 | return (canonicalSourceName == null |
427 | ? (canonicalSourceName = DBRefUtils | |
428 | .getCanonicalName(this.source)) | |
429 | : canonicalSourceName); | |
430 | } | |
431 | ||
432 | /** | |
433 | * | |
434 | * @param canonical | |
435 | */ | |
436 | 1104 | public void setCanonical(boolean canonical) |
437 | { | |
438 | 1104 | isCanonicalAccession = canonical; |
439 | } | |
440 | ||
441 | /** | |
442 | * | |
443 | * @return true if this is the primary canonical accession for the database | |
444 | * source | |
445 | */ | |
446 | 411 | public boolean isCanonical() |
447 | { | |
448 | // TODO Auto-generated method stub | |
449 | 411 | return isCanonicalAccession; |
450 | } | |
451 | } |