JAL-1620 version bump and release notes
[jalview.git] / src / jalview / io / packed / ParsePackedSet.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2b1)
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.packed;
22
23 import jalview.datamodel.AlignmentI;
24 import jalview.io.AppletFormatAdapter;
25 import jalview.io.FileParse;
26 import jalview.io.FormatAdapter;
27 import jalview.io.IdentifyFile;
28 import jalview.io.packed.DataProvider.JvDataType;
29
30 import java.io.BufferedReader;
31 import java.io.IOException;
32 import java.util.ArrayList;
33 import java.util.Hashtable;
34 import java.util.List;
35
36 public class ParsePackedSet
37 {
38
39   /**
40    * return results as a series of jalview.datamodel objects suitable for
41    * display
42    * 
43    * @param context
44    *          - context which is updated with new data
45    * @param files
46    *          - source data
47    * @return list of data objects added to context
48    * @throws Exception
49    */
50   public Object[] getAlignment(JalviewDataset context,
51           Iterable<DataProvider> files) throws Exception
52   {
53     List<Object> rslt = new ArrayList<Object>();
54     if (context == null)
55     {
56       context = new JalviewDataset();
57     }
58     boolean deuniquify = false;
59     for (DataProvider dta : files)
60     {
61       Exception exerror = null;
62       String errmsg = null;
63       FileParse src = dta.getDataSource();
64       if (dta.getType().equals(DataProvider.JvDataType.ALIGNMENT))
65       {
66         String fmt = null;
67         try
68         {
69           fmt = new IdentifyFile().Identify(src, false);
70         } catch (Exception ex)
71         {
72           exerror = ex;
73           errmsg = "Couldn't identify alignment format.";
74         }
75
76         if (fmt != null)
77         {
78           if (!FormatAdapter.isValidIOFormat(fmt, false))
79           {
80             errmsg = fmt;
81             exerror = null;
82           }
83           else
84           {
85             // parse the alignment
86             AlignmentI al = null;
87             try
88             {
89               al = new FormatAdapter().readFromFile(src, fmt);
90             } catch (Exception e)
91             {
92               errmsg = "Failed to parse alignment from result set";
93               exerror = e;
94             }
95             if (al != null)
96             {
97               // deuniquify and construct/merge additional dataset entries if
98               // necessary.
99               context.addAlignment(al);
100               context.updateSetModified(true);
101               rslt.add(al);
102               deuniquify = true;
103             }
104           }
105         }
106       }
107       if (dta.getType().equals(JvDataType.ANNOTATION))
108       {
109         if (!context.hasAlignments())
110         {
111           errmsg = "No alignment or sequence dataset to associate annotation with.";
112           // could duplicate the dataset reference here as default behaviour for
113           // sequence associated annotation ?
114         }
115         try
116         {
117           BufferedReader br;
118           if (src.getReader() instanceof BufferedReader)
119           {
120             br = (BufferedReader) src.getReader();
121           }
122           else
123           {
124             br = new BufferedReader(src.getReader());
125           }
126           if (new jalview.io.AnnotationFile().parseAnnotationFrom(
127                   context.getLastAlignment(), br))
128           {
129             context.updateSetModified(true);
130           }
131           else
132           {
133             errmsg = "Annotation file contained no data.";
134           }
135
136         } catch (Exception e)
137         {
138           errmsg = ((errmsg == null) ? "" : errmsg)
139                   + "Failed to parse the annotation file associated with the alignment.";
140           exerror = e;
141         }
142       }
143       if (dta.getType().equals(JvDataType.SEQASSOCATED))
144       {
145         if (!context.hasSequenceAssoc())
146         {
147           errmsg = "No sequence to associate data with.";
148
149         }
150         errmsg = "parsing of sequence associated data is not implemented";
151         exerror = new Exception(errmsg);
152       }
153       if (dta.getType().equals(JvDataType.FEATURES))
154       {
155         // check the context has a place to store feature rendering definitions,
156         // if not, create one.
157         if (context.featureColours == null)
158         {
159           context.featureColours = new Hashtable();
160         }
161         try
162         {
163           jalview.io.FeaturesFile ff = new jalview.io.FeaturesFile(src);
164           context.updateSetModified(ff.parse(context.getLastAlignment(),
165                   context.featureColours, false, context.relaxedIdMatching));
166         } catch (Exception e)
167         {
168           errmsg = ("Failed to parse the Features file associated with the alignment.");
169           exerror = e;
170         }
171       }
172       if (dta.getType().equals(JvDataType.TREE))
173       {
174         try
175         {
176           jalview.io.NewickFile nf = new jalview.io.NewickFile(src);
177           if (!nf.isValid())
178           {
179             nf.close();
180             nf = null;
181           }
182           else
183           {
184             // do association to current alignment.
185
186             context.addTreeFromFile(nf);
187             rslt.add(nf);
188             context.updateSetModified(true);
189           }
190         } catch (Exception e)
191         {
192           errmsg = ("Failed to parse the treeFile associated with the result.");
193           exerror = e;
194         }
195
196       }
197       if (exerror != null)
198       {
199         if (errmsg != null && errmsg.length() > 0)
200         {
201           throw new IOException(errmsg, exerror);
202         }
203         else
204         {
205           throw new IOException(errmsg, exerror);
206         }
207       }
208       else
209       {
210         if (errmsg != null && errmsg.length() > 0)
211         {
212           throw new IOException(errmsg);
213         }
214       }
215     }
216     if (deuniquify)
217     {
218       context.getLastAlignmentSet().deuniquifyAlignment();
219     }
220     return rslt.toArray();
221   }
222
223   /**
224    * simple command line test. Arguments should be one or more pairs of
225    * <DataProvider.JvDataType> <Filename> arguments. The routine will attempt to
226    * read each source in turn, and report what kind of Jalview datamodel objects
227    * would be created.
228    * 
229    * @param args
230    */
231   public static void main(String args[])
232   {
233     // make data providers from the set of keys/files
234     int i = 0;
235     List<DataProvider> dp = new ArrayList<DataProvider>();
236     while ((i + 1) < args.length)
237     {
238       String type = args[i++];
239       final String file = args[i++];
240       final JvDataType jtype = DataProvider.JvDataType.valueOf(type
241               .toUpperCase());
242       if (jtype != null)
243       {
244         final FileParse fp;
245         try
246         {
247           fp = new FileParse(file, AppletFormatAdapter.checkProtocol(file));
248         } catch (Exception e)
249         {
250           System.err.println("Couldn't handle datasource of type " + jtype
251                   + " using URI " + file);
252           e.printStackTrace();
253           return;
254         }
255         dp.add(new SimpleDataProvider(jtype, fp, null));
256       }
257       else
258       {
259         System.out.println("Couldn't parse source type token '"
260                 + type.toUpperCase() + "'");
261       }
262     }
263     if (i < args.length)
264     {
265       System.out.print("** WARNING\nIgnoring unused arguments:\n");
266       while (i < args.length)
267       {
268         System.out.print(" " + args[i]);
269       }
270       System.out.print("\n");
271
272     }
273     System.out.println("Now trying to parse set:");
274     JalviewDataset context;
275     Object[] newdm;
276     ParsePackedSet pps;
277     try
278     {
279       newdm = (pps = new ParsePackedSet()).getAlignment(
280               context = new JalviewDataset(), dp);
281     } catch (Exception e)
282     {
283       System.out.println("Test failed for these arguments.\n");
284       e.printStackTrace(System.out);
285       return;
286     }
287     if (newdm != null)
288     {
289       for (Object o : newdm)
290       {
291         System.out.println("Will need to create an " + o.getClass());
292       }
293
294       // now test uniquify/deuniquify stuff
295       // uniquify alignment and write alignment, annotation, features, and trees
296       // to buffers.
297       // import with deuniquify info, and compare results to input.
298
299     }
300     else
301     {
302       if (context.getLastAlignmentSet().isModified())
303       {
304         System.err
305                 .println("Initial alignment set was modified and any associated views should be updated.");
306       }
307     }
308   }
309 }