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