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