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