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