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