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