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