last version stay many bugs ..
[jalview.git] / src / jalview / io / AlignFile.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
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  */
18 package jalview.io;
19
20 import jalview.datamodel.Alignment;
21 import jalview.datamodel.AlignmentAnnotation;
22 import jalview.datamodel.Sequence;
23 import jalview.datamodel.SequenceI;
24
25 import java.io.IOException;
26 import java.util.Enumeration;
27 import java.util.Hashtable;
28 import java.util.Vector;
29
30 import javax.xml.parsers.ParserConfigurationException;
31
32 import org.xml.sax.SAXException;
33
34 import fr.orsay.lri.varna.exceptions.ExceptionFileFormatOrSyntax;
35 import fr.orsay.lri.varna.exceptions.ExceptionLoadingFailed;
36 import fr.orsay.lri.varna.exceptions.ExceptionPermissionDenied;
37 import fr.orsay.lri.varna.exceptions.ExceptionUnmatchedClosingParentheses;
38
39 /**
40  * DOCUMENT ME!
41  * 
42  * @author $author$
43  * @version $Revision$
44  */
45 public abstract class AlignFile extends FileParse
46 {
47   int noSeqs = 0;
48
49   int maxLength = 0;
50
51   /**
52    * Sequences to be added to form a new alignment.
53    */
54   protected Vector<SequenceI> seqs;
55
56   /**
57    * annotation to be added to generated alignment object
58    */
59   protected Vector annotations;
60
61   /**
62    * Properties to be added to generated alignment object
63    */
64   protected Hashtable properties;
65
66   long start;
67
68   long end;
69
70   boolean jvSuffix = true;
71
72   /**
73    * Creates a new AlignFile object.
74    */
75   public AlignFile()
76   {
77           // Shouldn't we init data structures
78           initData();
79   }
80
81   /**
82    * Constructor which parses the data from a file of some specified type.
83    * 
84    * @param inFile
85    *          Filename to read from.
86    * @param type
87    *          What type of file to read from (File, URL)
88  * @throws SAXException 
89  * @throws ParserConfigurationException 
90  * @throws ExceptionFileFormatOrSyntax 
91  * @throws ExceptionLoadingFailed 
92  * @throws ExceptionPermissionDenied 
93  * @throws InterruptedException 
94  * @throws ExceptionUnmatchedClosingParentheses 
95    */
96   public AlignFile(String inFile, String type) throws IOException, ExceptionFileFormatOrSyntax, ParserConfigurationException, SAXException, ExceptionPermissionDenied, ExceptionLoadingFailed, InterruptedException, ExceptionUnmatchedClosingParentheses
97   {
98     super(inFile, type);
99     initData();
100     parse();
101     // sets the index of each sequence in the alignment
102     for( int i=0,c=seqs.size(); i<c; i++ ) {  
103         seqs.get(i).setIndex(i);  
104     }
105   }
106
107   /**
108    * Attempt to read from the position where some other parsing process left
109    * off.
110    * 
111    * @param source
112    * @throws IOException
113  * @throws SAXException 
114  * @throws ParserConfigurationException 
115  * @throws ExceptionFileFormatOrSyntax 
116  * @throws ExceptionLoadingFailed 
117  * @throws ExceptionPermissionDenied 
118  * @throws InterruptedException 
119  * @throws ExceptionUnmatchedClosingParentheses 
120    */
121   public AlignFile(FileParse source) throws IOException, ExceptionFileFormatOrSyntax, ParserConfigurationException, SAXException, ExceptionPermissionDenied, ExceptionLoadingFailed, InterruptedException, ExceptionUnmatchedClosingParentheses
122   {
123     super(source);
124     initData();
125     parse();
126     // sets the index of each sequence in the alignment
127     for( int i=0,c=seqs.size(); i<c; i++ ) {  
128         seqs.get(i).setIndex(i);  
129     }
130   }
131
132   /**
133    * Return the seqs Vector
134    */
135   public Vector<SequenceI> getSeqs()
136   {
137     return seqs;
138   }
139
140   /**
141    * Return the Sequences in the seqs Vector as an array of Sequences
142    */
143   public SequenceI[] getSeqsAsArray()
144   {
145     SequenceI[] s = new SequenceI[seqs.size()];
146
147     for (int i = 0; i < seqs.size(); i++)
148     {
149       s[i] = (SequenceI) seqs.elementAt(i);
150     }
151
152     return s;
153   }
154
155   /**
156    * called by AppletFormatAdapter to generate an annotated alignment, rather
157    * than bare sequences.
158    * 
159    * @param al
160    */
161   public void addAnnotations(Alignment al)
162   {
163     addProperties(al);
164     for (int i = 0; i < annotations.size(); i++)
165     {
166       // detect if annotations.elementAt(i) rna secondary structure
167       // if so then do:
168       /*
169        * SequenceFeature[] pairArray =
170        * Rna.GetBasePairsFromAlignmentAnnotation(annotations.elementAt(i));
171        * Rna.HelixMap(pairArray);
172        */
173       AlignmentAnnotation an = (AlignmentAnnotation) annotations
174               .elementAt(i);
175       an.validateRangeAndDisplay();
176       al.addAnnotation(an);
177     }
178
179   }
180
181   /**
182    * Add any additional information extracted from the file to the alignment
183    * properties.
184    * 
185    * @note implicitly called by addAnnotations()
186    * @param al
187    */
188   public void addProperties(Alignment al)
189   {
190     if (properties != null && properties.size() > 0)
191     {
192       Enumeration keys = properties.keys();
193       Enumeration vals = properties.elements();
194       while (keys.hasMoreElements())
195       {
196         al.setProperty(keys.nextElement(), vals.nextElement());
197       }
198     }
199   }
200
201   /**
202    * Store a non-null key-value pair in a hashtable used to set alignment
203    * properties note: null keys will raise an error, null values will result in
204    * the key/value pair being silently ignored.
205    * 
206    * @param key
207    *          - non-null key object
208    * @param value
209    *          - non-null value
210    */
211   protected void setAlignmentProperty(Object key, Object value)
212   {
213     if (key == null)
214     {
215       throw new Error(
216               "Implementation error: Cannot have null alignment property key.");
217     }
218     if (value == null)
219     {
220       return; // null properties are ignored.
221     }
222     if (properties == null)
223     {
224       properties = new Hashtable();
225     }
226     properties.put(key, value);
227   }
228
229   protected Object getAlignmentProperty(Object key)
230   {
231     if (properties != null && key != null)
232     {
233       return properties.get(key);
234     }
235     return null;
236   }
237
238   /**
239    * Initialise objects to store sequence data in.
240    */
241   protected void initData()
242   {
243     seqs = new Vector();
244     annotations = new Vector();
245   }
246
247   /**
248    * DOCUMENT ME!
249    * 
250    * @param s
251    *          DOCUMENT ME!
252    */
253   protected void setSeqs(SequenceI[] s)
254   {
255     seqs = new Vector();
256
257     for (int i = 0; i < s.length; i++)
258     {
259       seqs.addElement(s[i]);
260     }
261   }
262
263   /**
264    * This method must be implemented to parse the contents of the file.
265  * @throws ExceptionFileFormatOrSyntax 
266  * @throws SAXException 
267  * @throws ParserConfigurationException 
268  * @throws ExceptionLoadingFailed 
269  * @throws ExceptionPermissionDenied 
270  * @throws InterruptedException 
271  * @throws ExceptionUnmatchedClosingParentheses 
272    */
273   public abstract void parse() throws IOException, ExceptionFileFormatOrSyntax, ParserConfigurationException, SAXException, ExceptionPermissionDenied, ExceptionLoadingFailed, InterruptedException, ExceptionUnmatchedClosingParentheses;
274
275   /**
276    * Print out in alignment file format the Sequences in the seqs Vector.
277    */
278   public abstract String print();
279
280   public void addJVSuffix(boolean b)
281   {
282     jvSuffix = b;
283   }
284
285   /**
286    * A general parser for ids.
287    * 
288    * @String id Id to be parsed
289    */
290   Sequence parseId(String id)
291   {
292     Sequence seq = null;
293     id = id.trim();
294     int space = id.indexOf(" ");
295     if (space > -1)
296     {
297       seq = new Sequence(id.substring(0, space), "");
298       seq.setDescription(id.substring(space + 1));
299     }
300     else
301     {
302       seq = new Sequence(id, "");
303     }
304
305     return seq;
306   }
307
308   /**
309    * Creates the output id. Adds prefix Uniprot format source|id And suffix
310    * Jalview /start-end
311    * 
312    * @String id Id to be parsed
313    */
314   String printId(SequenceI seq)
315   {
316     return seq.getDisplayId(jvSuffix);
317   }
318
319   /**
320    * vector of String[] treeName, newickString pairs
321    */
322   Vector newickStrings = null;
323
324   protected void addNewickTree(String treeName, String newickString)
325   {
326     if (newickStrings == null)
327     {
328       newickStrings = new Vector();
329     }
330     newickStrings.addElement(new String[]
331     { treeName, newickString });
332   }
333
334   protected int getTreeCount()
335   {
336     if (newickStrings == null)
337     {
338       return 0;
339     }
340     return newickStrings.size();
341   }
342
343 }