3a77b7301e5f7754f7b08e7068dced0bc40c5238
[jalview.git] / src / jalview / io / FileLoader.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
20 package jalview.io;
21
22 import java.util.*;
23
24 import javax.swing.*;
25
26 import jalview.datamodel.*;
27 import jalview.gui.*;
28
29 public class FileLoader implements Runnable
30 {
31   String file;
32
33   String protocol;
34
35   String format;
36
37   FileParse source = null; // alternative specification of where data comes
38
39   // from
40
41   AlignViewport viewport;
42
43   AlignFrame alignFrame;
44
45   long loadtime;
46
47   long memused;
48
49   boolean raiseGUI = true;
50   /**
51    * default constructor always raised errors in GUI dialog boxes 
52    */
53   public FileLoader() {
54     this(true);
55   }
56   /**
57    * construct a Fileloader that may raise errors non-interactively 
58    * @param raiseGUI true if errors are to be raised as GUI dialog boxes
59    */
60   public FileLoader(boolean raiseGUI)
61   {
62     this.raiseGUI = raiseGUI;
63   }
64
65   public void LoadFile(AlignViewport viewport, String file,
66           String protocol, String format)
67   {
68     this.viewport = viewport;
69     LoadFile(file, protocol, format);
70   }
71
72   public void LoadFile(String file, String protocol, String format)
73   {
74     this.file = file;
75     this.protocol = protocol;
76     this.format = format;
77
78     final Thread loader = new Thread(this);
79
80     SwingUtilities.invokeLater(new Runnable()
81     {
82       public void run()
83       {
84         loader.start();
85       }
86     });
87   }
88
89   /**
90    * Load a (file, protocol) source of unknown type
91    * 
92    * @param file
93    * @param protocol
94    */
95   public void LoadFile(String file, String protocol)
96   {
97     LoadFile(file, protocol, null);
98   }
99
100   /**
101    * Load alignment from (file, protocol) and wait till loaded
102    * 
103    * @param file
104    * @param protocol
105    * @return alignFrame constructed from file contents
106    */
107   public AlignFrame LoadFileWaitTillLoaded(String file, String protocol)
108   {
109     return LoadFileWaitTillLoaded(file, protocol, null);
110   }
111
112   /**
113    * Load alignment from (file, protocol) of type format and wait till loaded
114    * 
115    * @param file
116    * @param protocol
117    * @param format
118    * @return alignFrame constructed from file contents
119    */
120   public AlignFrame LoadFileWaitTillLoaded(String file, String protocol,
121           String format)
122   {
123     this.file = file;
124     this.protocol = protocol;
125     this.format = format;
126     return _LoadFileWaitTillLoaded();
127   }
128
129   /**
130    * Load alignment from FileParse source of type format and wait till loaded
131    * 
132    * @param source
133    * @param format
134    * @return alignFrame constructed from file contents
135    */
136   public AlignFrame LoadFileWaitTillLoaded(FileParse source, String format)
137   {
138     this.source = source;
139     file = source.getInFile();
140     protocol = source.type;
141     this.format = format;
142     return _LoadFileWaitTillLoaded();
143   }
144
145   /**
146    * start thread and wait until finished, then return the alignFrame that's
147    * (hopefully) been read.
148    * 
149    * @return
150    */
151   protected AlignFrame _LoadFileWaitTillLoaded()
152   {
153     Thread loader = new Thread(this);
154     loader.start();
155
156     while (loader.isAlive())
157     {
158       try
159       {
160         Thread.sleep(500);
161       } catch (Exception ex)
162       {
163       }
164     }
165
166     return alignFrame;
167   }
168
169   public void updateRecentlyOpened()
170   {
171     Vector recent = new Vector();
172
173     String type = protocol.equals(FormatAdapter.FILE) ? "RECENT_FILE"
174             : "RECENT_URL";
175
176     String historyItems = jalview.bin.Cache.getProperty(type);
177
178     StringTokenizer st;
179
180     if (historyItems != null)
181     {
182       st = new StringTokenizer(historyItems, "\t");
183
184       while (st.hasMoreTokens())
185       {
186         recent.addElement(st.nextElement().toString().trim());
187       }
188     }
189
190     if (recent.contains(file))
191     {
192       recent.remove(file);
193     }
194
195     StringBuffer newHistory = new StringBuffer(file);
196     for (int i = 0; i < recent.size() && i < 10; i++)
197     {
198       newHistory.append("\t");
199       newHistory.append(recent.elementAt(i));
200     }
201
202     jalview.bin.Cache.setProperty(type, newHistory.toString());
203
204     if (protocol.equals(FormatAdapter.FILE))
205     {
206       jalview.bin.Cache.setProperty("DEFAULT_FILE_FORMAT", format);
207     }
208   }
209
210   public void run()
211   {
212     String title = protocol.equals(AppletFormatAdapter.PASTE) ? "Copied From Clipboard"
213             : file;
214     Runtime rt = Runtime.getRuntime();
215     try
216     {
217       if (Desktop.instance != null)
218       {
219         Desktop.instance.startLoading(file);
220       }
221       if (format == null)
222       {
223         // just in case the caller didn't identify the file for us
224         if (source != null)
225         {
226           format = new IdentifyFile().Identify(source, false); // identify
227           // stream and
228           // rewind rather
229           // than close
230         }
231         else
232         {
233           format = new IdentifyFile().Identify(file, protocol);
234         }
235       }
236       if (Desktop.desktop != null && Desktop.desktop.isShowMemoryUsage())
237       {
238         System.gc();
239         memused = (rt.maxMemory() - rt.totalMemory() + rt.freeMemory()); // free memory before load
240       }
241       loadtime = -System.currentTimeMillis();
242       Alignment al = null;
243
244       if (format.equalsIgnoreCase("Jalview"))
245       {
246         if (source != null)
247         {
248           // Tell the user (developer?) that this is going to cause a problem
249           System.err
250                   .println("IMPLEMENTATION ERROR: Cannot read consecutive Jalview XML projects from a stream.");
251           // We read the data anyway - it might make sense.
252         }
253         alignFrame = new Jalview2XML(raiseGUI).LoadJalviewAlign(file);
254       }
255       else
256       {
257         String error = AppletFormatAdapter.SUPPORTED_FORMATS;
258         if (FormatAdapter.isValidFormat(format))
259         {
260           try
261           {
262             if (source != null)
263             {
264               // read from the provided source
265               al = new FormatAdapter().readFromFile(source, format);
266             }
267             else
268             {
269
270               // open a new source and read from it
271               FormatAdapter fa = new FormatAdapter();
272               al = fa.readFile(file, protocol, format);
273               source = fa.afile; // keep reference for later if necessary.
274             }
275           } catch (java.io.IOException ex)
276           {
277             error = ex.getMessage();
278           }
279         }
280         else
281         {
282           if (format != null && format.length() > 7)
283           {
284             // ad hoc message in format.
285             error = format + "\n" + error;
286           }
287         }
288
289         if ((al != null) && (al.getHeight() > 0))
290         {
291           if (viewport != null)
292           {
293             for (int i = 0; i < al.getHeight(); i++)
294             {
295               viewport.getAlignment().addSequence(al.getSequenceAt(i));
296             }
297             viewport.firePropertyChange("alignment", null, viewport
298                     .getAlignment().getSequences());
299
300           }
301           else
302           {
303             alignFrame = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH,
304                     AlignFrame.DEFAULT_HEIGHT);
305
306             alignFrame.statusBar.setText("Successfully loaded file "
307                     + title);
308
309             if (!protocol.equals(AppletFormatAdapter.PASTE))
310               alignFrame.setFileName(file, format);
311
312             Desktop.addInternalFrame(alignFrame, title,
313                     AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
314
315             try
316             {
317               alignFrame.setMaximum(jalview.bin.Cache.getDefault(
318                       "SHOW_FULLSCREEN", false));
319             } catch (java.beans.PropertyVetoException ex)
320             {
321             }
322           }
323         }
324         else
325         {
326           if (Desktop.instance != null)
327           {
328             Desktop.instance.stopLoading();
329           }
330
331           final String errorMessage = "Couldn't load file " + title + "\n"
332                   + error;
333           if (raiseGUI)
334           {
335             javax.swing.SwingUtilities.invokeLater(new Runnable()
336             {
337               public void run()
338               {
339                 JOptionPane.showInternalMessageDialog(Desktop.desktop,
340                         errorMessage, "Error loading file",
341                         JOptionPane.WARNING_MESSAGE);
342               }
343             });
344           }
345           else
346           {
347             System.err.println(errorMessage);
348           }
349         }
350       }
351
352       updateRecentlyOpened();
353
354     }
355     catch (Exception er)
356     {
357       System.err.println("Exception whilst opening file '"+file);
358       er.printStackTrace();
359       if (raiseGUI)
360       {
361         javax.swing.SwingUtilities.invokeLater(new Runnable()
362         {
363           public void run()
364           {
365             javax.swing.JOptionPane
366                     .showInternalMessageDialog(
367                             Desktop.desktop,
368                             "Encountered problems opening "
369                                     + file
370                                     + "!!"
371                                     , "File open error",
372                             javax.swing.JOptionPane.WARNING_MESSAGE);
373           }
374         });
375       }
376       alignFrame = null;
377     }
378     catch (OutOfMemoryError er)
379     {
380
381       er.printStackTrace();
382       alignFrame = null;
383       if (raiseGUI)
384       {
385         javax.swing.SwingUtilities.invokeLater(new Runnable()
386         {
387           public void run()
388           {
389             javax.swing.JOptionPane
390                     .showInternalMessageDialog(
391                             Desktop.desktop,
392                             "Out of memory loading file "
393                                     + file
394                                     + "!!"
395                                     + "\nSee help files for increasing Java Virtual Machine memory.",
396                             "Out of memory",
397                             javax.swing.JOptionPane.WARNING_MESSAGE);
398           }
399         });
400       }
401       else
402       {
403         System.err.println("Out of memory loading file " + file + "!!");
404       }
405     }
406     loadtime += System.currentTimeMillis();
407
408     if (Desktop.instance != null)
409     {
410       Desktop.instance.stopLoading();
411     }
412     // System.gc();
413     memused = memused - (rt.maxMemory() - rt.totalMemory() + rt.freeMemory()); // difference in free memory after load
414     if (alignFrame != null)
415     {
416       if (Desktop.desktop != null && Desktop.desktop.isShowMemoryUsage())
417       {
418         AlignmentI al = alignFrame.getViewport().getAlignment();
419
420         System.out.println("Loaded '" + title + "' in "
421                 + (loadtime / 1000.0) + "s, took an additional "
422                 + (1.0 * memused / (1024.0 * 1024.0)) + " MB ("
423                 + al.getHeight() + " seqs by " + al.getWidth() + " cols)");
424       }
425     }
426
427   }
428
429   /*
430    * (non-Javadoc)
431    * 
432    * @see java.lang.Object#finalize()
433    */
434   protected void finalize() throws Throwable
435   {
436     source = null;
437     alignFrame = null;
438     viewport = null;
439     super.finalize();
440   }
441
442 }