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