Clover icon

Coverage Report

  1. Project Clover database Mon Sep 2 2024 17:57:51 BST
  2. Package jalview.io

File FileLoader.java

 

Coverage histogram

../../img/srcFileCovDistChart7.png
29% of files have more coverage

Code metrics

92
186
21
1
707
504
83
0.45
8.86
21
3.95

Classes

Class Line # Actions
FileLoader 52 186 83
0.63879663.9%
 

Contributing tests

This file is covered by 147 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ 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;
22   
23    import java.io.File;
24    import java.io.IOException;
25    import java.util.StringTokenizer;
26    import java.util.Vector;
27   
28    import javax.swing.SwingUtilities;
29   
30    import jalview.api.ComplexAlignFile;
31    import jalview.api.FeatureSettingsModelI;
32    import jalview.api.FeaturesDisplayedI;
33    import jalview.api.FeaturesSourceI;
34    import jalview.bin.Cache;
35    import jalview.bin.Jalview;
36    import jalview.datamodel.AlignmentI;
37    import jalview.datamodel.HiddenColumns;
38    import jalview.datamodel.PDBEntry;
39    import jalview.datamodel.SequenceI;
40    import jalview.gui.AlignFrame;
41    import jalview.gui.AlignViewport;
42    import jalview.gui.Desktop;
43    import jalview.gui.JvOptionPane;
44    import jalview.gui.QuitHandler;
45    import jalview.json.binding.biojson.v1.ColourSchemeMapper;
46    import jalview.project.Jalview2XML;
47    import jalview.schemes.ColourSchemeI;
48    import jalview.structure.StructureSelectionManager;
49    import jalview.util.MessageManager;
50    import jalview.ws.utils.UrlDownloadClient;
51   
 
52    public class FileLoader implements Runnable
53    {
54    String file;
55   
56    DataSourceType protocol;
57   
58    FileFormatI format;
59   
60    AlignmentFileReaderI source = null; // alternative specification of where data
61    // comes
62   
63    // from
64   
65    AlignViewport viewport;
66   
67    AlignFrame alignFrame;
68   
69    long loadtime;
70   
71    long memused;
72   
73    boolean raiseGUI = true;
74   
75    private File selectedFile;
76   
77    private static boolean useDefaultFileFormat = false;
78   
79    /**
80    * default constructor always raised errors in GUI dialog boxes
81    */
 
82  122 toggle public FileLoader()
83    {
84  122 this(true);
85    }
86   
87    /**
88    * construct a Fileloader that may raise errors non-interactively
89    *
90    * @param raiseGUI
91    * true if errors are to be raised as GUI dialog boxes
92    */
 
93  425 toggle public FileLoader(boolean raiseGUI)
94    {
95  425 this.raiseGUI = raiseGUI;
96    }
97   
 
98  1 toggle public void LoadFile(AlignViewport viewport, Object file,
99    DataSourceType protocol, FileFormatI format)
100    {
101  1 LoadFile(viewport, file, protocol, format, true);
102    }
103   
 
104  21 toggle public void LoadFile(AlignViewport viewport, Object file,
105    DataSourceType protocol, FileFormatI format, boolean async)
106    {
107  21 this.viewport = viewport;
108  21 if (file instanceof File)
109    {
110  0 this.selectedFile = (File) file;
111  0 file = selectedFile.getPath();
112    }
113  21 LoadFile(file.toString(), protocol, format, async);
114    }
115   
 
116  0 toggle public void LoadFile(String file, DataSourceType protocol,
117    FileFormatI format)
118    {
119  0 LoadFile(file, protocol, format, true);
120    }
121   
 
122  21 toggle public void LoadFile(String file, DataSourceType protocol,
123    FileFormatI format, boolean async)
124    {
125  21 this.file = file;
126  21 this.protocol = protocol;
127  21 this.format = format;
128   
129  21 if (async)
130    {
131  1 final Thread loader = new Thread(this);
132   
133  1 SwingUtilities.invokeLater(new Runnable()
134    {
 
135  1 toggle @Override
136    public void run()
137    {
138  1 loader.start();
139    }
140    });
141    }
142    else
143    {
144  20 this.run();
145    }
146    }
147   
148    /**
149    * Load a (file, protocol) source of unknown type
150    *
151    * @param file
152    * @param protocol
153    */
 
154  0 toggle public void LoadFile(String file, DataSourceType protocol)
155    {
156  0 LoadFile(file, protocol, null);
157    }
158   
159    /**
160    * Load alignment from (file, protocol) and wait till loaded
161    *
162    * @param file
163    * @param sourceType
164    * @return alignFrame constructed from file contents
165    */
 
166  142 toggle public AlignFrame LoadFileWaitTillLoaded(String file,
167    DataSourceType sourceType)
168    {
169  142 return LoadFileWaitTillLoaded(file, sourceType, null);
170    }
171   
172    /**
173    * Load alignment from (file, protocol) of type format and wait till loaded
174    *
175    * @param file
176    * @param sourceType
177    * @param format
178    * @return alignFrame constructed from file contents
179    */
 
180  317 toggle public AlignFrame LoadFileWaitTillLoaded(String file,
181    DataSourceType sourceType, FileFormatI format)
182    {
183  317 this.file = file;
184  317 this.protocol = sourceType;
185  317 this.format = format;
186  317 return _LoadFileWaitTillLoaded();
187    }
188   
189    /**
190    * Load alignment from (file, protocol) of type format and wait till loaded
191    *
192    * @param file
193    * @param sourceType
194    * @param format
195    * @return alignFrame constructed from file contents
196    */
 
197  6 toggle public AlignFrame LoadFileWaitTillLoaded(File file,
198    DataSourceType sourceType, FileFormatI format)
199    {
200  6 this.selectedFile = file;
201  6 this.file = file.getPath();
202  6 this.protocol = sourceType;
203  6 this.format = format;
204  6 return _LoadFileWaitTillLoaded();
205    }
206   
207    /**
208    * Load alignment from FileParse source of type format and wait till loaded
209    *
210    * @param source
211    * @param format
212    * @return alignFrame constructed from file contents
213    */
 
214  0 toggle public AlignFrame LoadFileWaitTillLoaded(AlignmentFileReaderI source,
215    FileFormatI format)
216    {
217  0 this.source = source;
218   
219  0 file = source.getInFile();
220  0 protocol = source.getDataSourceType();
221  0 this.format = format;
222  0 return _LoadFileWaitTillLoaded();
223    }
224   
225    /**
226    * runs the 'run' method (in this thread), then return the alignFrame that's
227    * (hopefully) been read
228    *
229    * @return
230    */
 
231  323 toggle protected AlignFrame _LoadFileWaitTillLoaded()
232    {
233  323 this.run();
234   
235  319 return alignFrame;
236    }
237   
 
238  340 toggle public void updateRecentlyOpened()
239    {
240  340 Vector<String> recent = new Vector<>();
241  340 if (protocol == DataSourceType.PASTE)
242    {
243    // do nothing if the file was pasted in as text... there is no filename to
244    // refer to it as.
245  48 return;
246    }
247  292 if (file != null
248    && file.indexOf(System.getProperty("java.io.tmpdir")) > -1)
249    {
250    // ignore files loaded from the system's temporary directory
251  19 return;
252    }
253  273 String type = protocol == DataSourceType.FILE ? "RECENT_FILE"
254    : "RECENT_URL";
255   
256  273 String historyItems = Cache.getProperty(type);
257   
258  273 StringTokenizer st;
259   
260  273 if (historyItems != null)
261    {
262  261 st = new StringTokenizer(historyItems, "\t");
263   
264  2126 while (st.hasMoreTokens())
265    {
266  1865 recent.addElement(st.nextToken().trim());
267    }
268    }
269   
270  273 if (recent.contains(file))
271    {
272  185 recent.remove(file);
273    }
274   
275  273 StringBuffer newHistory = new StringBuffer(file);
276  1922 for (int i = 0; i < recent.size() && i < 10; i++)
277    {
278  1649 newHistory.append("\t");
279  1649 newHistory.append(recent.elementAt(i));
280    }
281   
282  273 Cache.setProperty(type, newHistory.toString());
283   
284  273 if (protocol == DataSourceType.FILE)
285    {
286  273 Cache.setProperty("DEFAULT_FILE_FORMAT", format.getName());
287    }
288    }
289   
 
290  344 toggle @Override
291    public void run()
292    {
293  344 String title = protocol == DataSourceType.PASTE
294    ? "Copied From Clipboard"
295    : file;
296  344 Runtime rt = Runtime.getRuntime();
297   
298  344 try
299    {
300  344 if (Desktop.instance != null)
301    {
302  293 Desktop.instance.startLoading(file);
303    }
304  344 if (format == null)
305    {
306    // just in case the caller didn't identify the file for us
307  162 if (source != null)
308    {
309  0 format = new IdentifyFile().identify(source, false);
310    // identify stream and rewind rather than close
311    }
312  162 else if (selectedFile != null)
313    {
314  0 format = new IdentifyFile().identify(selectedFile, protocol);
315    }
316    else
317    {
318  162 format = new IdentifyFile().identify(file, protocol);
319    }
320   
321    }
322   
323  344 if (format == null)
324    {
325  0 Desktop.instance.stopLoading();
326  0 jalview.bin.Console.errPrintln("The input file \"" + file
327    + "\" has null or unidentifiable data content!");
328  0 if (!Jalview.isHeadlessMode() && !Jalview.isBatchMode())
329    {
330  0 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
331    MessageManager.getString("label.couldnt_read_data")
332    + " in " + file + "\n"
333    + AppletFormatAdapter.getSupportedFormats(),
334    MessageManager.getString("label.couldnt_read_data"),
335    JvOptionPane.WARNING_MESSAGE);
336    }
337    // don't set shouldBeSaved if didn't load anything
338    // this.setShouldBeSaved();
339  0 return;
340    }
341    // TODO: cache any stream datasources as a temporary file (eg. PDBs
342    // retrieved via URL)
343  344 if (Desktop.desktop != null && Desktop.desktop.isShowMemoryUsage())
344    {
345  0 System.gc();
346  0 memused = (rt.maxMemory() - rt.totalMemory() + rt.freeMemory()); // free
347    // memory
348    // before
349    // load
350    }
351  344 loadtime = -System.currentTimeMillis();
352  344 AlignmentI al = null;
353   
354  344 if (FileFormat.Jalview.equals(format))
355    {
356  30 if (source != null)
357    {
358    // Tell the user (developer?) that this is going to cause a problem
359  0 jalview.bin.Console.errPrintln(
360    "IMPLEMENTATION ERROR: Cannot read consecutive Jalview XML projects from a stream.");
361    // We read the data anyway - it might make sense.
362    }
363    // BH 2018 switch to File object here instead of filename
364  30 alignFrame = new Jalview2XML(raiseGUI && !Jalview.isBatchMode())
365    .loadJalviewAlign(
366  30 selectedFile == null ? file : selectedFile);
367    }
368    else
369    {
370  314 String error = AppletFormatAdapter.getSupportedFormats();
371  314 try
372    {
373  314 if (source != null)
374    {
375    // read from the provided source
376  0 al = new FormatAdapter().readFromFile(source, format);
377    }
378    else
379    {
380   
381    // open a new source and read from it
382  314 FormatAdapter fa = new FormatAdapter();
383  314 boolean downloadStructureFile = format.isStructureFile()
384    && protocol.equals(DataSourceType.URL);
385  314 if (downloadStructureFile)
386    {
387  0 String structExt = format.getExtensions().split(",")[0];
388  0 String urlLeafName = file.substring(
389    file.lastIndexOf(
390    System.getProperty("file.separator")),
391    file.lastIndexOf("."));
392  0 String tempStructureFileStr = createNamedJvTempFile(
393    urlLeafName, structExt);
394   
395    // BH - switching to File object here so as to hold
396    // ._bytes array directly
397  0 File tempFile = new File(tempStructureFileStr);
398  0 UrlDownloadClient.download(file, tempFile);
399   
400  0 al = fa.readFile(tempFile, DataSourceType.FILE, format);
401  0 source = fa.getAlignFile();
402    }
403    else
404    {
405  314 if (selectedFile == null)
406    {
407  308 al = fa.readFile(null, file, protocol, format);
408   
409    }
410    else
411    {
412  6 al = fa.readFile(selectedFile, null, protocol, format);
413    }
414  314 source = fa.getAlignFile(); // keep reference for later if
415   
416    // necessary.
417    }
418    }
419    } catch (java.io.IOException ex)
420    {
421  0 error = ex.getMessage();
422    }
423   
424  314 if ((al != null) && (al.getHeight() > 0) && al.hasValidSequence())
425    {
426    // construct and register dataset sequences
427  314 for (SequenceI sq : al.getSequences())
428    {
429  2524 while (sq.getDatasetSequence() != null)
430    {
431  2 sq = sq.getDatasetSequence();
432    }
433  2522 if (sq.getAllPDBEntries() != null)
434    {
435  2522 for (PDBEntry pdbe : sq.getAllPDBEntries())
436    {
437    // register PDB entries with desktop's structure selection
438    // manager
439  50 StructureSelectionManager
440    .getStructureSelectionManager(Desktop.instance)
441    .registerPDBEntry(pdbe);
442    }
443    }
444    }
445   
446  314 FeatureSettingsModelI proxyColourScheme = source
447    .getFeatureColourScheme();
448  314 if (viewport != null)
449    {
450    // append to existing alignment
451  21 viewport.addAlignment(al, title);
452  21 viewport.applyFeaturesStyle(proxyColourScheme);
453    }
454    else
455    {
456    // otherwise construct the alignFrame
457   
458  293 if (source instanceof ComplexAlignFile)
459    {
460  0 HiddenColumns colSel = ((ComplexAlignFile) source)
461    .getHiddenColumns();
462  0 SequenceI[] hiddenSeqs = ((ComplexAlignFile) source)
463    .getHiddenSequences();
464  0 String colourSchemeName = ((ComplexAlignFile) source)
465    .getGlobalColourScheme();
466  0 FeaturesDisplayedI fd = ((ComplexAlignFile) source)
467    .getDisplayedFeatures();
468  0 alignFrame = new AlignFrame(al, hiddenSeqs, colSel,
469    AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
470  0 alignFrame.getViewport().setFeaturesDisplayed(fd);
471  0 alignFrame.getViewport().setShowSequenceFeatures(
472    ((ComplexAlignFile) source).isShowSeqFeatures());
473  0 ColourSchemeI cs = ColourSchemeMapper
474    .getJalviewColourScheme(colourSchemeName, al);
475  0 if (cs != null)
476    {
477  0 alignFrame.changeColour(cs);
478    }
479    }
480    else
481    {
482  293 alignFrame = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH,
483    AlignFrame.DEFAULT_HEIGHT);
484  289 if (source instanceof FeaturesSourceI)
485    {
486  1 alignFrame.getViewport().setShowSequenceFeatures(true);
487    }
488    }
489    // add metadata and update ui
490  289 if (!(protocol == DataSourceType.PASTE))
491    {
492  241 alignFrame.setFileName(file, format);
493  241 alignFrame.setFileObject(selectedFile); // BH 2018 SwingJS
494    }
495  289 if (proxyColourScheme != null)
496    {
497  14 alignFrame.getViewport()
498    .applyFeaturesStyle(proxyColourScheme);
499    }
500  289 alignFrame.setStatus(MessageManager.formatMessage(
501    "label.successfully_loaded_file", new String[]
502    { title }));
503   
504  289 if (raiseGUI)
505    {
506    // add the window to the GUI
507    // note - this actually should happen regardless of raiseGUI
508    // status in Jalview 3
509    // TODO: define 'virtual desktop' for benefit of headless scripts
510    // that perform queries to find the 'current working alignment'
511  216 Desktop.addInternalFrame(alignFrame, title,
512    AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
513   
514    /*
515    * for an Overview automatically opened with alignment,
516    * set its title now alignFrame title has been set
517    */
518  216 alignFrame.alignPanel.setOverviewTitle(alignFrame);
519    }
520   
521  289 try
522    {
523  289 alignFrame.setMaximum(
524    Cache.getDefault("SHOW_FULLSCREEN", false));
525    } catch (java.beans.PropertyVetoException ex)
526    {
527    }
528    }
529    }
530    else
531    {
532  0 if (Desktop.instance != null)
533    {
534  0 Desktop.instance.stopLoading();
535    }
536   
537  0 final String errorMessage = MessageManager.getString(
538    "label.couldnt_load_file") + " " + title + "\n" + error;
539    // TODO: refactor FileLoader to be independent of Desktop / Applet GUI
540    // bits ?
541  0 if (raiseGUI && !Jalview.isBatchMode() && Desktop.desktop != null)
542    {
543  0 javax.swing.SwingUtilities.invokeLater(new Runnable()
544    {
 
545  0 toggle @Override
546    public void run()
547    {
548  0 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
549    errorMessage,
550    MessageManager
551    .getString("label.error_loading_file"),
552    JvOptionPane.WARNING_MESSAGE);
553    }
554    });
555    }
556    else
557    {
558  0 jalview.bin.Console.errPrintln(errorMessage);
559    }
560    }
561    }
562   
563  340 updateRecentlyOpened();
564   
565    } catch (Exception er)
566    {
567  0 jalview.bin.Console
568    .errPrintln("Exception whilst opening file '" + file);
569  0 er.printStackTrace();
570  0 if (raiseGUI && !Jalview.isBatchMode())
571    {
572  0 javax.swing.SwingUtilities.invokeLater(new Runnable()
573    {
 
574  0 toggle @Override
575    public void run()
576    {
577  0 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
578    MessageManager.formatMessage(
579    "label.problems_opening_file", new String[]
580    { file }),
581    MessageManager.getString("label.file_open_error"),
582    JvOptionPane.WARNING_MESSAGE);
583    }
584    });
585    }
586  0 alignFrame = null;
587    } catch (OutOfMemoryError er)
588    {
589   
590  0 er.printStackTrace();
591  0 alignFrame = null;
592  0 if (raiseGUI && !Jalview.isBatchMode())
593    {
594  0 javax.swing.SwingUtilities.invokeLater(new Runnable()
595    {
 
596  0 toggle @Override
597    public void run()
598    {
599  0 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
600    MessageManager.formatMessage(
601    "warn.out_of_memory_loading_file", new String[]
602    { file }),
603    MessageManager.getString("label.out_of_memory"),
604    JvOptionPane.WARNING_MESSAGE);
605    }
606    });
607    }
608  0 jalview.bin.Console
609    .errPrintln("Out of memory loading file " + file + "!!");
610   
611    }
612  340 loadtime += System.currentTimeMillis();
613    // TODO: Estimate percentage of memory used by a newly loaded alignment -
614    // warn if more memory will be needed to work with it
615    // System.gc();
616  340 memused = memused
617    - (rt.maxMemory() - rt.totalMemory() + rt.freeMemory()); // difference
618    // in free
619    // memory
620    // after
621    // load
622  340 if (Desktop.desktop != null && Desktop.desktop.isShowMemoryUsage())
623    {
624  0 if (alignFrame != null)
625    {
626  0 AlignmentI al = alignFrame.getViewport().getAlignment();
627   
628  0 jalview.bin.Console.outPrintln("Loaded '" + title + "' in "
629    + (loadtime / 1000.0) + "s, took an additional "
630    + (1.0 * memused / (1024.0 * 1024.0)) + " MB ("
631    + al.getHeight() + " seqs by " + al.getWidth() + " cols)");
632    }
633    else
634    {
635    // report that we didn't load anything probably due to an out of memory
636    // error
637  0 jalview.bin.Console.outPrintln("Failed to load '" + title + "' in "
638    + (loadtime / 1000.0) + "s, took an additional "
639    + (1.0 * memused / (1024.0 * 1024.0))
640    + " MB (alignment is null)");
641    }
642    }
643    // remove the visual delay indicator
644  340 if (Desktop.instance != null)
645    {
646  289 Desktop.instance.stopLoading();
647    }
648   
649  340 this.setShouldBeSaved();
650    // after first file loaded we revert to assuming a default file format
651  340 useDefaultFileFormat = true;
652    }
653   
654    /**
655    * This method creates the file -
656    * {tmpdir}/jalview/{current_timestamp}/fileName.exetnsion using the supplied
657    * file name and extension
658    *
659    * @param fileName
660    * the name of the temp file to be created
661    * @param extension
662    * the extension of the temp file to be created
663    * @return
664    */
 
665  0 toggle private static String createNamedJvTempFile(String fileName,
666    String extension) throws IOException
667    {
668  0 String seprator = System.getProperty("file.separator");
669  0 String jvTempDir = System.getProperty("java.io.tmpdir") + "jalview"
670    + seprator + System.currentTimeMillis();
671  0 File tempStructFile = new File(
672    jvTempDir + seprator + fileName + "." + extension);
673  0 tempStructFile.mkdirs();
674  0 return tempStructFile.toString();
675    }
676   
677    /*
678    * set whether quit should ask to save when just loaded this source
679    */
 
680  340 toggle private void setShouldBeSaved()
681    {
682  340 if (protocol == null)
683  0 return;
684  340 AlignFrame af = this.alignFrame;
685  340 if (af == null)
686  21 return;
687  319 AlignViewport avp = af.getViewport();
688  319 if (avp == null)
689  0 return;
690  319 boolean upToDate = !protocol.isDynamic();
691  319 if (protocol.isUrl() && !Cache
692    .getDefault(PROMPT_SAVE_UNCHANGED_URL_ALIGNMENTS, true))
693    {
694  0 upToDate = true;
695    }
696  319 avp.setSavedUpToDate(upToDate,
697  319 upToDate ? null : QuitHandler.Message.UNSAVED_ALIGNMENTS);
698    }
699   
700    public static final String PROMPT_SAVE_UNCHANGED_URL_ALIGNMENTS = "PROMPT_SAVE_UNCHANGED_URL_ALIGNMENTS";
701   
 
702  75 toggle public static boolean getUseDefaultFileFormat()
703    {
704  75 return useDefaultFileFormat;
705    }
706   
707    }