FileParse object can be re-used to read different files concatenated together
[jalview.git] / src / jalview / io / ClustalFile.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.io;
20
21 import java.io.*;
22 import java.util.*;
23
24 import jalview.datamodel.*;
25 import jalview.util.*;
26
27 public class ClustalFile
28     extends AlignFile
29 {
30
31   public ClustalFile()
32   {
33   }
34
35   public ClustalFile(String inFile, String type)
36       throws IOException
37   {
38     super(inFile, type);
39   }
40   public ClustalFile(FileParse source) throws IOException
41   {
42     super(source);
43   }
44   public void initData()
45   {
46     super.initData();
47   }
48
49   public void parse()
50       throws IOException
51   {
52     int i = 0;
53     boolean flag = false;
54
55     Vector headers = new Vector();
56     Hashtable seqhash = new Hashtable();
57     StringBuffer tempseq;
58     String line, id;
59     StringTokenizer str;
60
61     try
62     {
63       while ( (line = nextLine()) != null)
64       {
65         if (line.indexOf(" ") != 0)
66         {
67           str = new StringTokenizer(line, " ");
68
69           if (str.hasMoreTokens())
70           {
71             id = str.nextToken();
72
73             if (id.equalsIgnoreCase("CLUSTAL"))
74             {
75               flag = true;
76             }
77             else
78             {
79               if (flag)
80               {
81                 if (seqhash.containsKey(id))
82                 {
83                   tempseq = (StringBuffer) seqhash.get(id);
84                 }
85                 else
86                 {
87                   tempseq = new StringBuffer();
88                   seqhash.put(id, tempseq);
89                 }
90
91                 if (! (headers.contains(id)))
92                 {
93                   headers.addElement(id);
94                 }
95
96                 if (str.hasMoreTokens())
97                 {
98                   tempseq.append(str.nextToken());
99                 }
100               }
101             }
102           }
103           else
104           {
105             flag = true;
106           }
107         }
108       }
109     }
110     catch (IOException e)
111     {
112       System.err.println("Exception parsing clustal file " + e);
113       e.printStackTrace();
114     }
115
116     if (flag)
117     {
118       this.noSeqs = headers.size();
119
120       //Add sequences to the hash
121       for (i = 0; i < headers.size(); i++)
122       {
123         if (seqhash.get(headers.elementAt(i)) != null)
124         {
125           if (maxLength < seqhash.get(headers.elementAt(i)).toString()
126               .length())
127           {
128             maxLength = seqhash.get(headers.elementAt(i)).toString()
129                 .length();
130           }
131
132           Sequence newSeq = parseId(headers.elementAt(i).toString());
133           newSeq.setSequence(seqhash.get(headers.elementAt(i).toString()).
134                              toString());
135
136           seqs.addElement(newSeq);
137         }
138         else
139         {
140           System.err.println(
141               "Clustal File Reader: Can't find sequence for " +
142               headers.elementAt(i));
143         }
144       }
145     }
146   }
147
148   public String print()
149   {
150     return print(getSeqsAsArray());
151   }
152
153   public String print(SequenceI[] s)
154   {
155     StringBuffer out = new StringBuffer("CLUSTAL\n\n");
156
157     int max = 0;
158     int maxid = 0;
159
160     int i = 0;
161
162     while ( (i < s.length) && (s[i] != null))
163     {
164       String tmp = printId(s[i]);
165
166       if (s[i].getSequence().length > max)
167       {
168         max = s[i].getSequence().length;
169       }
170
171       if (tmp.length() > maxid)
172       {
173         maxid = tmp.length();
174       }
175
176       i++;
177     }
178
179     if (maxid < 15)
180     {
181       maxid = 15;
182     }
183
184     maxid++;
185
186     int len = 60;
187     int nochunks = (max / len) + 1;
188
189     for (i = 0; i < nochunks; i++)
190     {
191       int j = 0;
192
193       while ( (j < s.length) && (s[j] != null))
194       {
195         out.append(new Format("%-" + maxid + "s").form(printId(s[j]) + " "));
196
197         int start = i * len;
198         int end = start + len;
199
200         if ( (end < s[j].getSequence().length) &&
201             (start < s[j].getSequence().length))
202         {
203           out.append(s[j].getSequenceAsString(start, end));
204         }
205         else
206         {
207           if (start < s[j].getSequence().length)
208           {
209             out.append(s[j].getSequenceAsString().substring(start));
210           }
211         }
212
213         out.append("\n");
214         j++;
215       }
216
217       out.append("\n");
218     }
219
220     return out.toString();
221   }
222 }