patch to fix occasional arrayoutofbounds exception when working with hidden columns...
[jalview.git] / src / jalview / util / DBRefUtils.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
3  * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.util;
20
21 import java.util.*;
22
23 import jalview.datamodel.*;
24
25 public class DBRefUtils
26 {
27   /**
28    * Utilities for handling DBRef objects and their collections.
29    */
30   /**
31    * 
32    * @param dbrefs
33    *                Vector of DBRef objects to search
34    * @param sources
35    *                String[] array of source DBRef IDs to retrieve
36    * @return Vector
37    */
38   public static DBRefEntry[] selectRefs(DBRefEntry[] dbrefs,
39           String[] sources)
40   {
41     if (dbrefs == null)
42     {
43       return null;
44     }
45     if (sources == null)
46     {
47       return dbrefs;
48     }
49     Hashtable srcs = new Hashtable();
50     Vector res = new Vector();
51
52     for (int i = 0; i < sources.length; i++)
53     {
54       srcs.put(new String(sources[i]), new Integer(i));
55     }
56     for (int i = 0, j = dbrefs.length; i < j; i++)
57     {
58       if (srcs.containsKey(dbrefs[i].getSource()))
59       {
60         res.addElement(dbrefs[i]);
61       }
62     }
63
64     if (res.size() > 0)
65     {
66       DBRefEntry[] reply = new DBRefEntry[res.size()];
67       for (int i = 0; i < res.size(); i++)
68       {
69         reply[i] = (DBRefEntry) res.elementAt(i);
70       }
71       return reply;
72     }
73     res = null;
74     // there are probable memory leaks in the hashtable!
75     return null;
76   }
77
78   /**
79    * isDasCoordinateSystem
80    * 
81    * @param string
82    *                String
83    * @param dBRefEntry
84    *                DBRefEntry
85    * @return boolean true if Source DBRefEntry is compatible with DAS
86    *         CoordinateSystem name
87    */
88   public static Hashtable DasCoordinateSystemsLookup = null;
89
90   public static boolean isDasCoordinateSystem(String string,
91           DBRefEntry dBRefEntry)
92   {
93     if (DasCoordinateSystemsLookup == null)
94     {
95       // TODO: Make a DasCoordinateSystemsLookup properties resource
96       // Initialise
97       DasCoordinateSystemsLookup = new Hashtable();
98       DasCoordinateSystemsLookup.put("pdbresnum",
99               jalview.datamodel.DBRefSource.PDB);
100       DasCoordinateSystemsLookup.put("uniprot",
101               jalview.datamodel.DBRefSource.UNIPROT);
102       DasCoordinateSystemsLookup.put("EMBL",
103               jalview.datamodel.DBRefSource.EMBL);
104       // DasCoordinateSystemsLookup.put("EMBL",
105       // jalview.datamodel.DBRefSource.EMBLCDS);
106     }
107
108     String coordsys = (String) DasCoordinateSystemsLookup.get(string
109             .toLowerCase());
110     if (coordsys != null)
111     {
112       return coordsys.equals(dBRefEntry.getSource());
113     }
114     return false;
115   }
116
117   public static Hashtable CanonicalSourceNameLookup = null;
118
119   /**
120    * look up source in an internal list of database reference sources and return
121    * the canonical jalview name for the source, or the original string if it has
122    * no canonical form.
123    * 
124    * @param source
125    * @return canonical jalview source (one of jalview.datamodel.DBRefSource.*)
126    *         or original source
127    */
128   public static String getCanonicalName(String source)
129   {
130     if (CanonicalSourceNameLookup == null)
131     {
132       CanonicalSourceNameLookup = new Hashtable();
133       CanonicalSourceNameLookup.put("uniprotkb/swiss-prot",
134               jalview.datamodel.DBRefSource.UNIPROT);
135       CanonicalSourceNameLookup.put("uniprotkb/trembl",
136               jalview.datamodel.DBRefSource.UNIPROT);
137       CanonicalSourceNameLookup.put("pdb",
138               jalview.datamodel.DBRefSource.PDB);
139     }
140     String canonical = (String) CanonicalSourceNameLookup.get(source
141             .toLowerCase());
142     if (canonical == null)
143     {
144       return source;
145     }
146     return canonical;
147   }
148
149   /**
150    * find RefEntry corresponding to a particular pattern the equals method of
151    * each entry is used, from String attributes right down to Mapping
152    * attributes.
153    * 
154    * @param ref
155    *                Set of references to search
156    * @param entry
157    *                pattern to collect - null any entry for wildcard match
158    * @return
159    */
160   public static DBRefEntry[] searchRefs(DBRefEntry[] ref, DBRefEntry entry)
161   {
162     return searchRefs(ref, entry,
163             matchDbAndIdAndEitherMapOrEquivalentMapList);
164   }
165
166   public static DBRefEntry[] searchRefs(DBRefEntry[] ref, DBRefEntry entry,
167           DbRefComp comparator)
168   {
169     if (ref == null || entry == null)
170       return null;
171     Vector rfs = new Vector();
172     for (int i = 0; i < ref.length; i++)
173     {
174       if (comparator.matches(entry, ref[i]))
175       {
176         rfs.addElement(ref[i]);
177       }
178     }
179     // TODO Auto-generated method stub
180     if (rfs.size() > 0)
181     {
182       DBRefEntry[] rf = new DBRefEntry[rfs.size()];
183       rfs.copyInto(rf);
184       return rf;
185     }
186     return null;
187   }
188
189   public interface DbRefComp
190   {
191     public boolean matches(DBRefEntry refa, DBRefEntry refb);
192   }
193
194   /**
195    * match on all non-null fields in refa
196    */
197   public static DbRefComp matchNonNullonA = new DbRefComp()
198   {
199     public boolean matches(DBRefEntry refa, DBRefEntry refb)
200     {
201       if (refa.getSource() == null
202               || refb.getSource().equals(refa.getSource()))
203       {
204         if (refa.getVersion() == null
205                 || refb.getVersion().equals(refa.getVersion()))
206         {
207           if (refa.getAccessionId() == null
208                   || refb.getAccessionId().equals(refa.getAccessionId()))
209           {
210             if (refa.getMap() == null
211                     || (refb.getMap() != null && refb.getMap().equals(
212                             refa.getMap())))
213             {
214               return true;
215             }
216           }
217         }
218       }
219       return false;
220     }
221   };
222
223   /**
224    * either field is null or field matches for all of source, version, accession
225    * id and map.
226    */
227   public static DbRefComp matchEitherNonNull = new DbRefComp()
228   {
229     public boolean matches(DBRefEntry refa, DBRefEntry refb)
230     {
231       if ((refa.getSource() == null || refb.getSource() == null)
232               || refb.getSource().equals(refa.getSource()))
233       {
234         if ((refa.getVersion() == null || refb.getVersion() == null)
235                 || refb.getVersion().equals(refa.getVersion()))
236         {
237           if ((refa.getAccessionId() == null || refb.getAccessionId() == null)
238                   || refb.getAccessionId().equals(refa.getAccessionId()))
239           {
240             if ((refa.getMap() == null || refb.getMap() == null)
241                     || (refb.getMap() != null && refb.getMap().equals(
242                             refa.getMap())))
243             {
244               return true;
245             }
246           }
247         }
248       }
249       return false;
250     }
251   };
252
253   /**
254    * accession ID and DB must be identical. Version is ignored. Map is either
255    * not defined or is a match (or is compatible?)
256    */
257   public static DbRefComp matchDbAndIdAndEitherMap = new DbRefComp()
258   {
259     public boolean matches(DBRefEntry refa, DBRefEntry refb)
260     {
261       if (refa.getSource() != null && refb.getSource() != null
262               && refb.getSource().equals(refa.getSource()))
263       {
264         // We dont care about version
265         // if ((refa.getVersion()==null || refb.getVersion()==null)
266         // || refb.getVersion().equals(refa.getVersion()))
267         // {
268         if (refa.getAccessionId() != null && refb.getAccessionId() != null
269                 || refb.getAccessionId().equals(refa.getAccessionId()))
270         {
271           if ((refa.getMap() == null || refb.getMap() == null)
272                   || (refa.getMap() != null && refb.getMap() != null && refb
273                           .getMap().equals(refa.getMap())))
274           {
275             return true;
276           }
277         }
278       }
279       return false;
280     }
281   };
282
283   /**
284    * accession ID and DB must be identical. Version is ignored. No map on either
285    * or map but no maplist on either or maplist of map on a is the complement of
286    * maplist of map on b.
287    */
288   public static DbRefComp matchDbAndIdAndComplementaryMapList = new DbRefComp()
289   {
290     public boolean matches(DBRefEntry refa, DBRefEntry refb)
291     {
292       if (refa.getSource() != null && refb.getSource() != null
293               && refb.getSource().equals(refa.getSource()))
294       {
295         // We dont care about version
296         // if ((refa.getVersion()==null || refb.getVersion()==null)
297         // || refb.getVersion().equals(refa.getVersion()))
298         // {
299         if (refa.getAccessionId() != null && refb.getAccessionId() != null
300                 || refb.getAccessionId().equals(refa.getAccessionId()))
301         {
302           if ((refa.getMap() == null && refb.getMap() == null)
303                   || (refa.getMap() != null && refb.getMap() != null))
304             if ((refb.getMap().getMap() == null && refa.getMap().getMap() == null)
305                     || (refb.getMap().getMap() != null
306                             && refa.getMap().getMap() != null && refb
307                             .getMap().getMap().getInverse().equals(
308                                     refa.getMap().getMap())))
309             {
310               return true;
311             }
312         }
313       }
314       return false;
315     }
316   };
317
318   /**
319    * accession ID and DB must be identical. Version is ignored. No map on both
320    * or or map but no maplist on either or maplist of map on a is equivalent to
321    * the maplist of map on b.
322    */
323   public static DbRefComp matchDbAndIdAndEquivalentMapList = new DbRefComp()
324   {
325     public boolean matches(DBRefEntry refa, DBRefEntry refb)
326     {
327       if (refa.getSource() != null && refb.getSource() != null
328               && refb.getSource().equals(refa.getSource()))
329       {
330         // We dont care about version
331         // if ((refa.getVersion()==null || refb.getVersion()==null)
332         // || refb.getVersion().equals(refa.getVersion()))
333         // {
334         if (refa.getAccessionId() != null && refb.getAccessionId() != null
335                 || refb.getAccessionId().equals(refa.getAccessionId()))
336         {
337           if (refa.getMap() == null && refb.getMap() == null)
338           {
339             return true;
340           }
341           if (refa.getMap() != null
342                   && refb.getMap() != null
343                   && ((refb.getMap().getMap() == null && refa.getMap()
344                           .getMap() == null) || (refb.getMap().getMap() != null
345                           && refa.getMap().getMap() != null && refb
346                           .getMap().getMap().equals(refa.getMap().getMap()))))
347           {
348             return true;
349           }
350         }
351       }
352       return false;
353     }
354   };
355
356   /**
357    * accession ID and DB must be identical. Version is ignored. No map on either
358    * or map but no maplist on either or maplist of map on a is equivalent to the
359    * maplist of map on b.
360    */
361   public static DbRefComp matchDbAndIdAndEitherMapOrEquivalentMapList = new DbRefComp()
362   {
363     public boolean matches(DBRefEntry refa, DBRefEntry refb)
364     {
365       if (refa.getSource() != null && refb.getSource() != null
366               && refb.getSource().equals(refa.getSource()))
367       {
368         // We dont care about version
369         // if ((refa.getVersion()==null || refb.getVersion()==null)
370         // || refb.getVersion().equals(refa.getVersion()))
371         // {
372         if (refa.getAccessionId() != null && refb.getAccessionId() != null
373                 && refb.getAccessionId().equals(refa.getAccessionId()))
374         {
375           if (refa.getMap() == null || refb.getMap() == null)
376           {
377             return true;
378           }
379           if ((refa.getMap() != null && refb.getMap() != null)
380                   && (refb.getMap().getMap() == null && refa.getMap()
381                           .getMap() == null)
382                   || (refb.getMap().getMap() != null
383                           && refa.getMap().getMap() != null && refb
384                           .getMap().getMap().equals(refa.getMap().getMap())))
385           {
386             return true;
387           }
388         }
389       }
390       return false;
391     }
392   };
393
394   /**
395    * used by file parsers to generate DBRefs from annotation within file (eg
396    * stockholm)
397    * 
398    * @param dbname
399    * @param version
400    * @param acn
401    * @param seq
402    *                where to anotate with reference
403    * @return parsed version of entry that was added to seq (if any)
404    */
405   public static DBRefEntry parseToDbRef(SequenceI seq, String dbname,
406           String version, String acn)
407   {
408     DBRefEntry ref = null;
409     if (dbname != null)
410     {
411       String locsrc = jalview.util.DBRefUtils.getCanonicalName(dbname);
412       if (locsrc.equals(jalview.datamodel.DBRefSource.PDB))
413       {
414         // check for chaincode and mapping
415         // PFAM style stockhom PDB citation
416         com.stevesoft.pat.Regex r = new com.stevesoft.pat.Regex(
417                 "([0-9][0-9A-Za-z]{3})\\s*(.?)\\s*;([0-9]+)-([0-9]+)");
418         if (r.search(acn.trim()))
419         {
420           String pdbid = r.stringMatched(1);
421           String chaincode = r.stringMatched(2);
422           String mapstart = r.stringMatched(3);
423           String mapend = r.stringMatched(4);
424           if (chaincode.equals(" "))
425           {
426             chaincode = "_";
427           }
428           // construct pdb ref.
429           ref = new DBRefEntry(locsrc, version, pdbid + chaincode);
430           PDBEntry pdbr = new PDBEntry();
431           pdbr.setId(pdbid);
432           seq.addPDBId(pdbr);
433         }
434       }
435       else
436       {
437         // default:
438         ref = new DBRefEntry(locsrc, version, acn);
439       }
440     }
441     if (ref != null)
442     {
443       seq.addDBRef(ref);
444     }
445     return ref;
446   }
447
448 }