ascii type
[jalview.git] / src / jalview / datamodel / xdb / embl / EmblEntry.java
1 package jalview.datamodel.xdb.embl;
2
3 import jalview.datamodel.DBRefEntry;
4 import jalview.datamodel.Sequence;
5 import jalview.datamodel.SequenceFeature;
6 import jalview.datamodel.SequenceI;
7
8 import java.util.Enumeration;
9 import java.util.Hashtable;
10 import java.util.Iterator;
11 import java.util.Vector;
12
13 public class EmblEntry {
14   String accession;
15   String version;
16   String taxDivision;
17   String desc;
18   String rCreated;
19   String rLastUpdated;
20   String lastUpdated;
21   Vector keywords;
22   Vector refs;
23   Vector dbRefs;
24   Vector features;
25   EmblSequence sequence;
26   /**
27    * @return the accession
28    */
29   public String getAccession() {
30     return accession;
31   }
32   /**
33    * @param accession the accession to set
34    */
35   public void setAccession(String accession) {
36     this.accession = accession;
37   }
38   /**
39    * @return the dbRefs
40    */
41   public Vector getDbRefs() {
42     return dbRefs;
43   }
44   /**
45    * @param dbRefs the dbRefs to set
46    */
47   public void setDbRefs(Vector dbRefs) {
48     this.dbRefs = dbRefs;
49   }
50   /**
51    * @return the desc
52    */
53   public String getDesc() {
54     return desc;
55   }
56   /**
57    * @param desc the desc to set
58    */
59   public void setDesc(String desc) {
60     this.desc = desc;
61   }
62   /**
63    * @return the features
64    */
65   public Vector getFeatures() {
66     return features;
67   }
68   /**
69    * @param features the features to set
70    */
71   public void setFeatures(Vector features) {
72     this.features = features;
73   }
74   /**
75    * @return the keywords
76    */
77   public Vector getKeywords() {
78     return keywords;
79   }
80   /**
81    * @param keywords the keywords to set
82    */
83   public void setKeywords(Vector keywords) {
84     this.keywords = keywords;
85   }
86   /**
87    * @return the lastUpdated
88    */
89   public String getLastUpdated() {
90     return lastUpdated;
91   }
92   /**
93    * @param lastUpdated the lastUpdated to set
94    */
95   public void setLastUpdated(String lastUpdated) {
96     this.lastUpdated = lastUpdated;
97   }
98   /**
99    * @return the refs
100    */
101   public Vector getRefs() {
102     return refs;
103   }
104   /**
105    * @param refs the refs to set
106    */
107   public void setRefs(Vector refs) {
108     this.refs = refs;
109   }
110   /**
111    * @return the releaseCreated
112    */
113   public String getRCreated() {
114     return rCreated;
115   }
116   /**
117    * @param releaseCreated the releaseCreated to set
118    */
119   public void setRcreated(String releaseCreated) {
120     this.rCreated = releaseCreated;
121   }
122   /**
123    * @return the releaseLastUpdated
124    */
125   public String getRLastUpdated() {
126     return rLastUpdated;
127   }
128   /**
129    * @param releaseLastUpdated the releaseLastUpdated to set
130    */
131   public void setRLastUpdated(String releaseLastUpdated) {
132     this.rLastUpdated = releaseLastUpdated;
133   }
134   /**
135    * @return the sequence
136    */
137   public EmblSequence getSequence() {
138     return sequence;
139   }
140   /**
141    * @param sequence the sequence to set
142    */
143   public void setSequence(EmblSequence sequence) {
144     this.sequence = sequence;
145   }
146   /**
147    * @return the taxDivision
148    */
149   public String getTaxDivision() {
150     return taxDivision;
151   }
152   /**
153    * @param taxDivision the taxDivision to set
154    */
155   public void setTaxDivision(String taxDivision) {
156     this.taxDivision = taxDivision;
157   }
158   /**
159    * @return the version
160    */
161   public String getVersion() {
162     return version;
163   }
164   /**
165    * @param version the version to set
166    */
167   public void setVersion(String version) {
168     this.version = version;
169   }
170 /*
171  * EMBL Feature support is limited. The text below is included for the benefit of
172  * any developer working on improving EMBL feature import in Jalview.
173  * Extract from EMBL feature specification
174  * see http://www.embl-ebi.ac.uk/embl/Documentation/FT_definitions/feature_table.html
175 3.5 Location
176 3.5.1 Purpose
177
178 The location indicates the region of the presented sequence which corresponds 
179 to a feature. 
180
181 3.5.2 Format and conventions
182 The location contains at least one sequence location descriptor and may 
183 contain one or more operators with one or more sequence location descriptors. 
184 Base numbers refer to the numbering in the entry. This numbering designates 
185 the first base (5' end) of the presented sequence as base 1. 
186 Base locations beyond the range of the presented sequence may not be used in 
187 location descriptors, the only exception being location in a remote entry (see 
188 3.5.2.1, e).  
189
190 Location operators and descriptors are discussed in more detail below.  
191
192 3.5.2.1 Location descriptors
193
194 The location descriptor can be one of the following: 
195 (a) a single base number
196 (b) a site between two indicated adjoining bases
197 (c) a single base chosen from within a specified range of bases (not allowed for new
198     entries)
199 (d) the base numbers delimiting a sequence span
200 (e) a remote entry identifier followed by a local location descriptor
201     (i.e., a-d)
202
203 A site between two adjoining nucleotides, such as endonucleolytic cleavage 
204 site, is indicated by listing the two points separated by a carat (^). The 
205 permitted formats for this descriptor are n^n+1 (for example 55^56), or, for 
206 circular molecules, n^1, where "n" is the full length of the molecule, ie 
207 1000^1 for circular molecule with length 1000.
208
209 A single base chosen from a range of bases is indicated by the first base
210 number and the last base number of the range separated by a single period
211 (e.g., '12.21' indicates a single base taken from between the indicated
212 points). From October 2006 the usage of this descriptor is restricted :
213 it is illegal to use "a single base from a range" (c) either on its own or
214 in combination with the "sequence span" (d) descriptor for newly created entries.
215 The existing entries where such descriptors exist are going to be retrofitted.
216
217 Sequence spans are indicated by the starting base number and the ending base 
218 number separated by two periods (e.g., '34..456'). The '<' and '>' symbols may 
219 be used with the starting and ending base numbers to indicate that an end 
220 point is beyond the specified base number. The starting and ending base 
221 positions can be represented as distinct base numbers ('34..456') or a site 
222 between two indicated adjoining bases. 
223
224 A location in a remote entry (not the entry to which the feature table 
225 belongs) can be specified by giving  the accession-number and sequence version 
226 of the remote entry, followed by a colon ":", followed by a location 
227 descriptor which applies to that entry's sequence (i.e. J12345.1:1..15, see 
228 also examples below) 
229
230 3.5.2.2 Operators
231
232 The location operator is a prefix that specifies what must be done to the 
233 indicated sequence to find or construct the location corresponding to the 
234 feature. A list of operators is given below with their definitions and most 
235 common format. 
236
237 complement(location) 
238 Find the complement of the presented sequence in the span specified by "
239 location" (i.e., read the complement of the presented strand in its 5'-to-3' 
240 direction) 
241
242 join(location,location, ... location) 
243 The indicated elements should be joined (placed end-to-end) to form one 
244 contiguous sequence 
245
246 order(location,location, ... location) 
247 The elements can be found in the 
248 specified order (5' to 3' direction), but nothing is implied about the 
249 reasonableness about joining them 
250
251 Note : location operator "complement" can be used in combination with either "
252 join" or "order" within the same location; combinations of "join" and "order" 
253 within the same location (nested operators) are illegal.
254
255
256
257 3.5.3 Location examples 
258
259 The following is a list of common location descriptors with their meanings: 
260
261 Location                  Description   
262
263 467                       Points to a single base in the presented sequence 
264
265 340..565                  Points to a continuous range of bases bounded by and
266                           including the starting and ending bases
267
268 <345..500                 Indicates that the exact lower boundary point of a feature
269                           is unknown.  The location begins at some  base previous to
270                           the first base specified (which need not be contained in 
271                           the presented sequence) and continues to and includes the 
272                           ending base 
273
274 <1..888                   The feature starts before the first sequenced base and 
275                           continues to and includes base 888
276
277 1..>888                   The feature starts at the first sequenced base and 
278                           continues beyond base 888
279
280 102.110                   Indicates that the exact location is unknown but that it is 
281                           one of the bases between bases 102 and 110, inclusive
282
283 123^124                   Points to a site between bases 123 and 124
284
285 join(12..78,134..202)     Regions 12 to 78 and 134 to 202 should be joined to form 
286                           one contiguous sequence
287
288
289 complement(34..126)       Start at the base complementary to 126 and finish at the 
290                           base complementary to base 34 (the feature is on the strand 
291                           complementary to the presented strand)
292
293
294 complement(join(2691..4571,4918..5163))
295                           Joins regions 2691 to 4571 and 4918 to 5163, then 
296                           complements the joined segments (the feature is on the 
297                           strand complementary to the presented strand) 
298
299 join(complement(4918..5163),complement(2691..4571))
300                        Complements regions 4918 to 5163 and 2691 to 4571, then 
301                           joins the complemented segments (the feature is on the 
302                           strand complementary to the presented strand)
303   
304 J00194.1:100..202         Points to bases 100 to 202, inclusive, in the entry (in 
305                           this database) with primary accession number 'J00194'
306  
307 join(1..100,J00194.1:100..202)
308                           Joins region 1..100 of the existing entry with the region
309                           100..202 of remote entry J00194
310
311  */
312   /**
313    * Recover annotated sequences from EMBL file
314    * @param noNa don't return nucleic acid sequences 
315    * @param sourceDb TODO
316    * @param noProtein don't return any translated protein sequences marked in features
317    * @return dataset sequences with DBRefs and features - DNA always comes first
318    */
319   public jalview.datamodel.SequenceI[] getSequences(boolean noNa, boolean noPeptide, String sourceDb) {
320     Vector seqs=new Vector();
321     Sequence dna=null;
322     if (!noNa) {
323       dna = new Sequence(sourceDb+"|"+accession, sequence.getSequence());
324       dna.setDescription(desc);
325       dna.addDBRef(new DBRefEntry(sourceDb, version, accession));
326       // TODO: add mapping for parentAccession attribute
327       // TODO: transform EMBL Database refs to canonical form
328       if (dbRefs!=null)
329         for (Iterator i=dbRefs.iterator(); i.hasNext(); dna.addDBRef((DBRefEntry)i.next()));
330     }
331     for (Iterator i=features.iterator(); i.hasNext(); ) {
332       EmblFeature feature = (EmblFeature) i.next();
333       if (!noNa) {
334         if (feature.dbRefs!=null && feature.dbRefs.size()>0) {
335           for (Iterator dbr=feature.dbRefs.iterator(); dbr.hasNext(); dna.addDBRef((DBRefEntry)dbr.next()) )
336             ;
337         }
338       }
339       if (feature.getName().equalsIgnoreCase("CDS")) {
340         // extract coding region(s)
341         jalview.datamodel.Mapping map = null;
342         int[] exon=null;
343         if (feature.locations!=null && feature.locations.size()>0) {
344           for (Iterator locs=feature.locations.iterator();
345           locs.hasNext(); ) {
346             EmblFeatureLocations loc = (EmblFeatureLocations) locs.next();
347             int[] se = loc.getElementRanges();
348             if (exon==null) {
349               exon=se;
350             } else {
351               int[] t=new int[exon.length+se.length];
352               System.arraycopy(exon, 0, t, 0, exon.length);
353               System.arraycopy(se, 0, t, exon.length,se.length);
354               exon=t;
355             }
356           }
357         }
358         String prseq=null;
359         String prname=new String();
360         String prid=null;
361         Hashtable vals=new Hashtable();
362         int prstart=1;
363         // get qualifiers
364         if (feature.getQualifiers()!=null && feature.getQualifiers().size()>0) {
365           for (Iterator quals=feature.getQualifiers().iterator(); quals.hasNext(); ) {
366             Qualifier q = (Qualifier) quals.next();
367             if (q.getName().equals("translation")) 
368             {
369               prseq=q.getValue();
370             } 
371             else
372               if (q.getName().equals("protein_id")) 
373               {
374                 prid=q.getValue();
375               }
376               else
377                 if (q.getName().equals("codon_start"))
378                 {
379                   prstart = Integer.parseInt(q.getValue());
380                 }
381                 else 
382                 if (q.getName().equals("product")){
383                   prname = q.getValue();
384                 } else {
385                   // throw anything else into the additional properties hash
386                   vals.put(q.getName(), q.getValue());
387                 }
388           }
389         }
390         Sequence product=null;
391         if (prseq!=null && prname!=null && prid!=null) {
392           // extract proteins.
393           if (!noPeptide) {
394             product = new Sequence(sourceDb+"|"+"EMBLCDS|"+prid+"|"+prname, prseq, prstart, prstart+prseq.length()-1);
395             product.setDescription("Protein Product from "+sourceDb);
396             seqs.add(product);
397           }
398           // we have everything - create the mapping and perhaps the protein sequence
399           map = new jalview.datamodel.Mapping(product, exon, new int[] { prstart, prstart+prseq.length()-1}, 3, 1);
400           // add cds feature to dna seq - this may include the stop codon
401           for (int xint=0;xint<exon.length; xint+=2) {
402             SequenceFeature sf = new SequenceFeature();
403             sf.setBegin(exon[xint]);
404             sf.setEnd(exon[xint+1]);
405             sf.setType(feature.getName());
406             sf.setFeatureGroup(jalview.datamodel.DBRefSource.EMBL);
407             sf.setDescription("Exon "+(1+xint)+" for protein '"+prname+"' EMBLCDS:"+prid);
408             if (vals!=null && vals.size()>0) {
409               Enumeration kv = vals.elements();
410               while (kv.hasMoreElements()) {
411                 Object key=kv.nextElement();
412                 if (key!=null)
413                   sf.setValue(key.toString(), vals.get(key));
414               }
415             }
416             dna.addSequenceFeature(sf);
417           }
418         }
419         // add dbRefs to sequence
420         if (feature.dbRefs!=null && feature.dbRefs.size()>0) 
421         {
422           for (Iterator dbr=feature.dbRefs.iterator(); dbr.hasNext();  ) 
423           {
424             DBRefEntry ref = (DBRefEntry)dbr.next();
425             ref.setSource(jalview.util.DBRefUtils.getCanonicalName(ref.getSource()));
426             if (ref.getSource().equals(jalview.datamodel.DBRefSource.UNIPROT)) 
427             {
428               ref.setMap(map);
429             }
430             if (product!=null) {
431               DBRefEntry pref = new DBRefEntry(ref.getSource(), ref.getVersion(), ref.getAccessionId());
432               pref.setMap(null); // reference is direct
433             }
434             dna.addDBRef(ref);
435           }
436         }
437         
438       } else {
439         // General feature type.
440         if (!noNa) {
441           if (feature.dbRefs!=null && feature.dbRefs.size()>0) {
442             for (Iterator dbr=feature.dbRefs.iterator(); dbr.hasNext(); dna.addDBRef((DBRefEntry)dbr.next()) )
443               ;
444           }
445         }
446       }
447
448     }
449     if (!noNa) {
450       seqs.add(dna);
451     }
452     SequenceI[] sqs = new SequenceI[seqs.size()];
453     for (int i=0,j=seqs.size();i<j; i++) {
454       sqs[i] = (SequenceI) seqs.elementAt(i);
455       seqs.set(i, null);
456     }
457     return sqs;
458   }
459 }