todo
[jalview.git] / src / jalview / util / DBRefUtils.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2007 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 Vector of DBRef objects to search
33    * @param sources String[] array of source DBRef IDs to retrieve
34    * @return Vector
35    */
36   public static DBRefEntry[] selectRefs(DBRefEntry[] dbrefs, String[] sources)
37   {
38     if (dbrefs == null)
39     {
40       return null;
41     }
42     if (sources == null)
43     {
44       return dbrefs;
45     }
46     Hashtable srcs = new Hashtable();
47     Vector res = new Vector();
48
49     for (int i = 0; i < sources.length; i++)
50     {
51       srcs.put(new String(sources[i]), new Integer(i));
52     }
53     for (int i = 0, j = dbrefs.length; i < j; i++)
54     {
55       if (srcs.containsKey(dbrefs[i].getSource()))
56       {
57         res.addElement(dbrefs[i]);
58       }
59     }
60
61     if (res.size() > 0)
62     {
63       DBRefEntry[] reply = new DBRefEntry[res.size()];
64       for (int i = 0; i < res.size(); i++)
65       {
66         reply[i] = (DBRefEntry) res.elementAt(i);
67       }
68       return reply;
69     }
70     res = null;
71     // there are probable  memory leaks in the hashtable!
72     return null;
73   }
74
75   /**
76    * isDasCoordinateSystem
77    *
78    * @param string String
79    * @param dBRefEntry DBRefEntry
80    * @return boolean true if Source DBRefEntry is compatible with DAS CoordinateSystem name
81    */
82   public static Hashtable DasCoordinateSystemsLookup = null;
83   public static boolean isDasCoordinateSystem(String string,
84                                               DBRefEntry dBRefEntry)
85   {
86     if (DasCoordinateSystemsLookup == null)
87     { 
88       // TODO: Make a DasCoordinateSystemsLookup properties resource
89       // Initialise
90       DasCoordinateSystemsLookup = new Hashtable();
91       DasCoordinateSystemsLookup.put("pdbresnum",
92                                      jalview.datamodel.DBRefSource.PDB);
93       DasCoordinateSystemsLookup.put("uniprot",
94                                      jalview.datamodel.DBRefSource.UNIPROT);
95       DasCoordinateSystemsLookup.put("EMBL",
96               jalview.datamodel.DBRefSource.EMBL);
97       //DasCoordinateSystemsLookup.put("EMBL",
98       //        jalview.datamodel.DBRefSource.EMBLCDS);
99     }
100
101     String coordsys = (String) DasCoordinateSystemsLookup.get(string.
102         toLowerCase());
103     if (coordsys != null)
104     {
105       return coordsys.equals(dBRefEntry.getSource());
106     }
107     return false;
108   }
109   public static Hashtable CanonicalSourceNameLookup=null;
110   /**
111    * look up source in an internal list of database reference sources
112    * and return the canonical jalview name for the source, or the original
113    * string if it has no canonical form.
114    * @param source
115    * @return canonical jalview source (one of jalview.datamodel.DBRefSource.*) or original source
116    */
117   public static String getCanonicalName(String source)
118   {
119     if (CanonicalSourceNameLookup==null) {
120       CanonicalSourceNameLookup = new Hashtable();
121       CanonicalSourceNameLookup.put("uniprotkb/swiss-prot", jalview.datamodel.DBRefSource.UNIPROT);
122       CanonicalSourceNameLookup.put("uniprotkb/trembl", jalview.datamodel.DBRefSource.UNIPROT);
123       CanonicalSourceNameLookup.put("pdb", jalview.datamodel.DBRefSource.PDB);
124     }
125     String canonical = (String) CanonicalSourceNameLookup.get(source.
126         toLowerCase());
127     if (canonical==null)
128     {
129       return source;
130     }
131     return canonical;
132   }
133   /**
134    * find RefEntry corresponding to a particular pattern
135    * the equals method of each entry is used, from String attributes right down to Mapping attributes.
136    * @param ref Set of references to search
137    * @param entry pattern to collect - null any entry for wildcard match
138    * @return
139    */
140   public static DBRefEntry[] searchRefs(DBRefEntry[] ref, DBRefEntry entry)
141   {
142     return searchRefs(ref, entry, matchDbAndIdAndEitherMapOrEquivalentMapList);
143   }
144   public static DBRefEntry[] searchRefs(DBRefEntry[] ref, DBRefEntry entry, DbRefComp comparator)
145   {
146     if (ref==null || entry==null)
147       return null;
148     Vector rfs = new Vector();
149     for (int i=0; i<ref.length;i++)
150     {
151       if (comparator.matches(entry, ref[i]))
152       {
153               rfs.addElement(ref[i]);
154       }
155     }
156     // TODO Auto-generated method stub
157     if (rfs.size()>0)
158     {
159       DBRefEntry[] rf = new DBRefEntry[rfs.size()];
160       rfs.copyInto(rf);
161       return rf;
162     }
163     return null;
164   }
165   public interface DbRefComp {
166     public boolean matches(DBRefEntry refa, DBRefEntry refb);
167   }
168   /**
169    * match on all non-null fields in refa
170    */
171   public static DbRefComp matchNonNullonA = new DbRefComp()
172     {
173           public boolean matches(DBRefEntry refa, DBRefEntry refb)
174           {
175             if (refa.getSource()==null || refb.getSource().equals(refa.getSource()))
176             {
177               if (refa.getVersion()==null || refb.getVersion().equals(refa.getVersion()))
178               {
179                 if (refa.getAccessionId()==null || refb.getAccessionId().equals(refa.getAccessionId()))
180                 {
181                   if (refa.getMap()==null || (refb.getMap()!=null && refb.getMap().equals(refa.getMap())))
182                   {
183                     return true; 
184                   }
185                 }
186               }
187             }
188             return false;
189           }
190     };
191     /**
192      * either field is null or field matches for all of source, version, accession id and map.
193      */
194     public static DbRefComp matchEitherNonNull = new DbRefComp()
195     {
196           public boolean matches(DBRefEntry refa, DBRefEntry refb)
197           {
198             if ((refa.getSource()==null || refb.getSource()==null) 
199                     || refb.getSource().equals(refa.getSource()))
200             {
201               if ((refa.getVersion()==null || refb.getVersion()==null) 
202                       || refb.getVersion().equals(refa.getVersion()))
203               {
204                 if ((refa.getAccessionId()==null || refb.getAccessionId()==null) 
205                         || refb.getAccessionId().equals(refa.getAccessionId()))
206                 {
207                   if ((refa.getMap()==null || refb.getMap()==null) 
208                           || (refb.getMap()!=null && refb.getMap().equals(refa.getMap())))
209                   {
210                     return true; 
211                   }
212                 }
213               }
214             }
215             return false;
216           }
217     };
218     /**
219      * accession ID and DB must be identical. Version is ignored. Map is either not defined or is a match (or is compatible?)
220      */
221     public static DbRefComp matchDbAndIdAndEitherMap = new DbRefComp()
222     {
223           public boolean matches(DBRefEntry refa, DBRefEntry refb)
224           {
225             if (refa.getSource()!=null && refb.getSource()!=null 
226                     && refb.getSource().equals(refa.getSource()))
227             {
228               // We dont care about version
229               //if ((refa.getVersion()==null || refb.getVersion()==null) 
230               //        || refb.getVersion().equals(refa.getVersion()))
231               //{
232               if (refa.getAccessionId()!=null && refb.getAccessionId()!=null 
233                       || refb.getAccessionId().equals(refa.getAccessionId()))
234                 {
235                   if ((refa.getMap()==null || refb.getMap()==null) 
236                           || (refa.getMap()!=null && refb.getMap()!=null && refb.getMap().equals(refa.getMap())))
237                   {
238                     return true; 
239                   }
240                 }
241               }
242             return false;
243           }
244     };
245     /**
246      * accession ID and DB must be identical. Version is ignored. 
247      * No map on either or map but no maplist on either or maplist of map on a is the complement of maplist of map on b.
248      */
249     public static DbRefComp matchDbAndIdAndComplementaryMapList = new DbRefComp()
250     {
251           public boolean matches(DBRefEntry refa, DBRefEntry refb)
252           {
253             if (refa.getSource()!=null && refb.getSource()!=null 
254                     && refb.getSource().equals(refa.getSource()))
255             {
256               // We dont care about version
257               //if ((refa.getVersion()==null || refb.getVersion()==null) 
258               //        || refb.getVersion().equals(refa.getVersion()))
259               //{
260               if (refa.getAccessionId()!=null && refb.getAccessionId()!=null 
261                       || refb.getAccessionId().equals(refa.getAccessionId()))
262                 {
263                   if ((refa.getMap()==null && refb.getMap()==null) 
264                           || (refa.getMap()!=null && refb.getMap()!=null))
265                     if ((refb.getMap().getMap()==null && refa.getMap().getMap()==null)
266                             || (refb.getMap().getMap()!=null && refa.getMap().getMap()!=null
267                             && refb.getMap().getMap().getInverse().equals(refa.getMap().getMap())))
268                   {
269                     return true; 
270                   }
271                 }
272               }
273             return false;
274           }
275     };
276     /**
277      * accession ID and DB must be identical. Version is ignored. 
278      * No map on both or or map but no maplist on either or maplist of map on a is equivalent to the maplist of map on b.
279      */
280     public static DbRefComp matchDbAndIdAndEquivalentMapList = new DbRefComp()
281     {
282           public boolean matches(DBRefEntry refa, DBRefEntry refb)
283           {
284             if (refa.getSource()!=null && refb.getSource()!=null 
285                     && refb.getSource().equals(refa.getSource()))
286             {
287               // We dont care about version
288               //if ((refa.getVersion()==null || refb.getVersion()==null) 
289               //        || refb.getVersion().equals(refa.getVersion()))
290               //{
291               if (refa.getAccessionId()!=null && refb.getAccessionId()!=null 
292                       || refb.getAccessionId().equals(refa.getAccessionId()))
293                 {
294                   if (refa.getMap()==null && refb.getMap()==null)
295                   {
296                     return true;
297                   }
298                   if (refa.getMap()!=null && refb.getMap()!=null
299                           && ((refb.getMap().getMap()==null && refa.getMap().getMap()==null)
300                             || (refb.getMap().getMap()!=null && refa.getMap().getMap()!=null
301                             && refb.getMap().getMap().equals(refa.getMap().getMap()))))
302                   {
303                     return true; 
304                   }
305                 }
306               }
307             return false;
308           }
309     };
310     /**
311      * accession ID and DB must be identical. Version is ignored. 
312      * No map on either or map but no maplist on either or maplist of map on a is equivalent to the maplist of map on b.
313      */
314     public static DbRefComp matchDbAndIdAndEitherMapOrEquivalentMapList = new DbRefComp()
315     {
316           public boolean matches(DBRefEntry refa, DBRefEntry refb)
317           {
318             if (refa.getSource()!=null && refb.getSource()!=null 
319                     && refb.getSource().equals(refa.getSource()))
320             {
321               // We dont care about version
322               //if ((refa.getVersion()==null || refb.getVersion()==null) 
323               //        || refb.getVersion().equals(refa.getVersion()))
324               //{
325               if (refa.getAccessionId()!=null && refb.getAccessionId()!=null 
326                       && refb.getAccessionId().equals(refa.getAccessionId()))
327                 {
328                   if (refa.getMap()==null || refb.getMap()==null)
329                   {
330                     return true;
331                   }
332                   if ((refa.getMap()!=null && refb.getMap()!=null)
333                           && (refb.getMap().getMap()==null && refa.getMap().getMap()==null)
334                             || (refb.getMap().getMap()!=null && refa.getMap().getMap()!=null
335                             && refb.getMap().getMap().equals(refa.getMap().getMap())))
336                   {
337                     return true; 
338                   }
339                 }
340               }
341             return false;
342           }
343     };
344     /**
345      * used by file parsers to generate DBRefs from annotation within file (eg stockholm)
346      * @param dbname
347      * @param version
348      * @param acn
349      * @param seq where to anotate with reference
350      * @return parsed version of entry that was added to seq (if any)
351      */
352     public static DBRefEntry parseToDbRef(SequenceI seq, String dbname, String version,
353             String acn)
354     {
355       DBRefEntry ref = null;
356       if (dbname!=null)
357       {
358         String locsrc = jalview.util.DBRefUtils
359         .getCanonicalName(dbname);
360         if (locsrc.equals(jalview.datamodel.DBRefSource.PDB))
361         {
362           // check for chaincode and mapping
363           // PFAM style stockhom PDB citation
364           com.stevesoft.pat.Regex r = new com.stevesoft.pat.Regex("([0-9][0-9A-Za-z]{3})\\s*(.?)\\s*;([0-9]+)-([0-9]+)");
365           if (r.search(acn.trim()))
366           {
367             String pdbid = r.stringMatched(1);
368             String chaincode = r.stringMatched(2);
369             String mapstart = r.stringMatched(3);
370             String mapend = r.stringMatched(4);
371             if (chaincode.equals(" "))
372             {
373               chaincode = "_";
374             }
375             // construct pdb ref.
376             ref = new DBRefEntry(locsrc, version, pdbid+chaincode);
377             PDBEntry pdbr = new PDBEntry();
378             pdbr.setId(pdbid);
379             seq.addPDBId(pdbr);
380           }
381         } else {
382           // default:
383           ref = new DBRefEntry(locsrc, version, acn);
384         }
385       }
386       if (ref!=null)
387       {
388         seq.addDBRef(ref);
389       }
390       return ref;
391     }
392         
393           
394 }