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