96cd8dba943f9111a254de5a0496b66c882e882d
[jalview.git] / src / jalview / util / DBRefUtils.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
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 of the License, or (at your option) any later version.
10  *  
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  * The Jalview Authors are detailed in the 'AUTHORS' file.
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()
308                             .equals(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       // System.err.println("Comparing A: "+refa.getSrcAccString()+(refa.hasMap()?" has map.":"."));
366       // System.err.println("Comparing B: "+refb.getSrcAccString()+(refb.hasMap()?" has map.":"."));
367       if (refa.getSource() != null && refb.getSource() != null
368               && refb.getSource().equals(refa.getSource()))
369       {
370         // We dont care about version
371         // if ((refa.getVersion()==null || refb.getVersion()==null)
372         // || refb.getVersion().equals(refa.getVersion()))
373         // {
374         if (refa.getAccessionId() != null && refb.getAccessionId() != null
375                 && refb.getAccessionId().equals(refa.getAccessionId()))
376         {
377           if (refa.getMap() == null || refb.getMap() == null)
378           {
379             return true;
380           }
381           if ((refa.getMap() != null && refb.getMap() != null)
382                   && (refb.getMap().getMap() == null && refa.getMap()
383                           .getMap() == null)
384                   || (refb.getMap().getMap() != null
385                           && refa.getMap().getMap() != null && (refb
386                           .getMap().getMap().equals(refa.getMap().getMap()))))
387           { // getMap().getMap().containsEither(false,refa.getMap().getMap())
388             return true;
389           }
390         }
391       }
392       return false;
393     }
394   };
395
396   /**
397    * used by file parsers to generate DBRefs from annotation within file (eg
398    * stockholm)
399    * 
400    * @param dbname
401    * @param version
402    * @param acn
403    * @param seq
404    *          where to anotate with reference
405    * @return parsed version of entry that was added to seq (if any)
406    */
407   public static DBRefEntry parseToDbRef(SequenceI seq, String dbname,
408           String version, String acn)
409   {
410     DBRefEntry ref = null;
411     if (dbname != null)
412     {
413       String locsrc = jalview.util.DBRefUtils.getCanonicalName(dbname);
414       if (locsrc.equals(jalview.datamodel.DBRefSource.PDB))
415       {
416         // check for chaincode and mapping
417         // PFAM style stockhom PDB citation
418         com.stevesoft.pat.Regex r = new com.stevesoft.pat.Regex(
419                 "([0-9][0-9A-Za-z]{3})\\s*(.?)\\s*;([0-9]+)-([0-9]+)");
420         if (r.search(acn.trim()))
421         {
422           String pdbid = r.stringMatched(1);
423           String chaincode = r.stringMatched(2);
424           String mapstart = r.stringMatched(3);
425           String mapend = r.stringMatched(4);
426           if (chaincode.equals(" "))
427           {
428             chaincode = "_";
429           }
430           // construct pdb ref.
431           ref = new DBRefEntry(locsrc, version, pdbid + chaincode);
432           PDBEntry pdbr = new PDBEntry();
433           pdbr.setId(pdbid);
434           seq.addPDBId(pdbr);
435         }
436       }
437       else
438       {
439         // default:
440         ref = new DBRefEntry(locsrc, version, acn);
441       }
442     }
443     if (ref != null)
444     {
445       seq.addDBRef(ref);
446     }
447     return ref;
448   }
449
450 }