Clover icon

Coverage Report

  1. Project Clover database Mon Nov 18 2024 09:56:54 GMT
  2. Package jalview.io

File AppletFormatAdapter.java

 

Coverage histogram

../../img/srcFileCovDistChart3.png
52% of files have more coverage

Code metrics

98
205
19
1
721
522
86
0.42
10.79
19
4.53

Classes

Class Line # Actions
AppletFormatAdapter 50 205 86
0.304347830.4%
 

Contributing tests

This file is covered by 213 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.io.InputStream;
26    import java.util.List;
27    import java.util.Locale;
28   
29    import jalview.api.AlignExportSettingsI;
30    import jalview.api.AlignmentViewPanel;
31    import jalview.datamodel.Alignment;
32    import jalview.datamodel.AlignmentAnnotation;
33    import jalview.datamodel.AlignmentI;
34    import jalview.datamodel.AlignmentView;
35    import jalview.datamodel.PDBEntry.Type;
36    import jalview.datamodel.SequenceI;
37    import jalview.ext.jmol.JmolParser;
38    import jalview.structure.StructureImportSettings;
39    import jalview.util.Platform;
40   
41    /**
42    * A low level class for alignment and feature IO with alignment formatting
43    * methods used by both applet and application for generating flat alignment
44    * files. It also holds the lists of magic format names that the applet and
45    * application will allow the user to read or write files with.
46    *
47    * @author $author$
48    * @version $Revision$
49    */
 
50    public class AppletFormatAdapter
51    {
52    private AlignmentViewPanel viewpanel;
53   
54    /**
55    * add jalview-derived non-secondary structure annotation from PDB structure
56    */
57    boolean annotFromStructure = false;
58   
59    /**
60    * add secondary structure from PDB data with built-in algorithms
61    */
62    boolean localSecondaryStruct = false;
63   
64    /**
65    * process PDB data with web services
66    */
67    boolean serviceSecondaryStruct = false;
68   
69    private AlignmentFileReaderI alignFile = null;
70   
71    String inFile;
72   
73    /**
74    * character used to write newlines
75    */
76    protected String newline = System.getProperty("line.separator");
77   
78    private AlignExportSettingsI exportSettings;
79   
80    private File selectedFile;
81   
82    public static String INVALID_CHARACTERS = "Contains invalid characters";
83   
84    /**
85    * Returns an error message with a list of supported readable file formats
86    *
87    * @return
88    */
 
89  314 toggle public static String getSupportedFormats()
90    {
91  314 return "Formats currently supported are\n"
92    + prettyPrint(FileFormats.getInstance().getReadableFormats());
93    }
94   
 
95  553 toggle public AppletFormatAdapter()
96    {
97    }
98   
 
99  2 toggle public AppletFormatAdapter(AlignmentViewPanel viewpanel)
100    {
101  2 this.viewpanel = viewpanel;
102    }
103   
 
104  126 toggle public AppletFormatAdapter(AlignmentViewPanel alignPanel,
105    AlignExportSettingsI settings)
106    {
107  126 viewpanel = alignPanel;
108  126 exportSettings = settings;
109    }
110   
111    /**
112    * Formats a grammatically correct(ish) list consisting of the given objects
113    *
114    * @param things
115    * @return
116    */
 
117  314 toggle public static String prettyPrint(List<? extends Object> things)
118    {
119  314 StringBuffer list = new StringBuffer();
120  5966 for (int i = 0, iSize = things.size() - 1; i < iSize; i++)
121    {
122  5652 list.append(things.get(i).toString());
123  5652 list.append(", ");
124    }
125    // could i18n 'and' here
126  314 list.append(" and " + things.get(things.size() - 1).toString() + ".");
127  314 return list.toString();
128    }
129   
 
130  0 toggle public void setNewlineString(String nl)
131    {
132  0 newline = nl;
133    }
134   
 
135  0 toggle public String getNewlineString()
136    {
137  0 return newline;
138    }
139   
140    /**
141    * Constructs the correct filetype parser for a characterised datasource
142    *
143    * @param inFile
144    * data/data location
145    * @param sourceType
146    * type of datasource
147    * @param fileFormat
148    *
149    * @return
150    */
 
151  195 toggle public AlignmentI readFile(String file, DataSourceType sourceType,
152    FileFormatI fileFormat) throws IOException
153    {
154  195 return readFile(null, file, sourceType, fileFormat);
155    }
156   
 
157  510 toggle public AlignmentI readFile(File selectedFile, String file,
158    DataSourceType sourceType, FileFormatI fileFormat)
159    throws IOException
160    {
161  510 return readFile(selectedFile, file, sourceType, fileFormat, null);
162    }
163   
 
164  510 toggle public AlignmentI readFile(File selectedFile, String file,
165    DataSourceType sourceType, FileFormatI fileFormat,
166    StructureImportSettings.TFType tempfacType) throws IOException
167    {
168   
169  510 this.selectedFile = selectedFile;
170  510 this.inFile = selectedFile != null ? selectedFile.getPath() : file;
171  510 try
172    {
173  510 if (fileFormat.isStructureFile())
174    {
175  18 String structureParser = StructureImportSettings
176    .getDefaultPDBFileParser();
177  18 boolean isParseWithJMOL = structureParser.equalsIgnoreCase(
178    StructureImportSettings.StructureParser.JMOL_PARSER
179    .toString());
180  18 StructureImportSettings.addSettings(annotFromStructure,
181    localSecondaryStruct, serviceSecondaryStruct);
182  18 if (tempfacType != null)
183    {
184  0 StructureImportSettings.setTemperatureFactorType(tempfacType);
185    }
186  18 if (isParseWithJMOL)
187    {
188    // needs a File option
189  15 alignFile = new JmolParser(
190  15 selectedFile == null ? inFile : selectedFile, sourceType,
191    StructureImportSettings.getTemperatureFactorType());
192    }
193    else
194    {
195    // todo is mc_view parsing obsolete yet? JAL-2120
196  3 StructureImportSettings.setShowSeqFeatures(true);
197  3 alignFile = new mc_view.PDBfile(annotFromStructure,
198    localSecondaryStruct, serviceSecondaryStruct, inFile,
199    sourceType);
200    }
201  18 ((StructureFile) alignFile).setDbRefType(
202  18 FileFormat.PDB.equals(fileFormat) ? Type.PDB : Type.MMCIF);
203    }
204  492 else if (selectedFile != null)
205    {
206  7 alignFile = fileFormat
207    .getReader(new FileParse(selectedFile, sourceType));
208    }
209    else
210    {
211    // alignFile = fileFormat.getAlignmentFile(inFile, sourceType);
212  485 alignFile = fileFormat.getReader(new FileParse(inFile, sourceType));
213    }
214  510 return buildAlignmentFromFile();
215    } catch (Exception e)
216    {
217  0 e.printStackTrace();
218  0 jalview.bin.Console.errPrintln("Failed to read alignment using the '"
219    + fileFormat + "' reader.\n" + e);
220   
221  0 if (e.getMessage() != null
222    && e.getMessage().startsWith(INVALID_CHARACTERS))
223    {
224  0 throw new IOException(e.getMessage());
225    }
226   
227    // Finally test if the user has pasted just the sequence, no id
228  0 if (sourceType == DataSourceType.PASTE)
229    {
230  0 try
231    {
232    // Possible sequence is just residues with no label
233  0 alignFile = new FastaFile(">UNKNOWN\n" + inFile,
234    DataSourceType.PASTE);
235  0 return buildAlignmentFromFile();
236   
237    } catch (Exception ex)
238    {
239  0 if (ex.toString().startsWith(INVALID_CHARACTERS))
240    {
241  0 throw new IOException(e.getMessage());
242    }
243   
244  0 ex.printStackTrace();
245    }
246    }
247  0 if (FileFormat.Html.equals(fileFormat))
248    {
249  0 throw new IOException(e.getMessage());
250    }
251    }
252  0 throw new FileFormatException(getSupportedFormats());
253    }
254   
255    /**
256    * Constructs the correct filetype parser for an already open datasource
257    *
258    * @param source
259    * an existing datasource
260    * @param format
261    * File format of data that will be provided by datasource
262    *
263    * @return
264    */
 
265  0 toggle public AlignmentI readFromFile(FileParse source, FileFormatI format)
266    throws IOException
267    {
268  0 this.inFile = source.getInFile();
269  0 DataSourceType type = source.dataSourceType;
270  0 try
271    {
272  0 if (FileFormat.PDB.equals(format) || FileFormat.MMCif.equals(format))
273    {
274    // TODO obtain config value from preference settings
275  0 boolean isParseWithJMOL = false;
276  0 if (isParseWithJMOL)
277    {
278  0 StructureImportSettings.addSettings(annotFromStructure,
279    localSecondaryStruct, serviceSecondaryStruct);
280  0 alignFile = new JmolParser(source);
281    }
282    else
283    {
284  0 StructureImportSettings.setShowSeqFeatures(true);
285  0 alignFile = new mc_view.PDBfile(annotFromStructure,
286    localSecondaryStruct, serviceSecondaryStruct, source);
287    }
288  0 ((StructureFile) alignFile).setDbRefType(Type.PDB);
289    }
290    else
291    {
292  0 alignFile = format.getReader(source);
293    }
294   
295  0 return buildAlignmentFromFile();
296   
297    } catch (Exception e)
298    {
299  0 e.printStackTrace();
300  0 jalview.bin.Console.errPrintln("Failed to read alignment using the '"
301    + format + "' reader.\n" + e);
302   
303  0 if (e.getMessage() != null
304    && e.getMessage().startsWith(INVALID_CHARACTERS))
305    {
306  0 throw new FileFormatException(e.getMessage());
307    }
308   
309    // Finally test if the user has pasted just the sequence, no id
310  0 if (type == DataSourceType.PASTE)
311    {
312  0 try
313    {
314    // Possible sequence is just residues with no label
315  0 alignFile = new FastaFile(">UNKNOWN\n" + inFile,
316    DataSourceType.PASTE);
317  0 return buildAlignmentFromFile();
318   
319    } catch (Exception ex)
320    {
321  0 if (ex.toString().startsWith(INVALID_CHARACTERS))
322    {
323  0 throw new IOException(e.getMessage());
324    }
325   
326  0 ex.printStackTrace();
327    }
328    }
329   
330    // If we get to this stage, the format was not supported
331  0 throw new FileFormatException(getSupportedFormats());
332    }
333    }
334   
335    /**
336    * boilerplate method to handle data from an AlignFile and construct a new
337    * alignment or import to an existing alignment
338    *
339    * @return AlignmentI instance ready to pass to a UI constructor
340    */
 
341  510 toggle private AlignmentI buildAlignmentFromFile()
342    {
343    // Standard boilerplate for creating alignment from parser
344    // alignFile.configureForView(viewpanel);
345   
346  510 AlignmentI al = new Alignment(alignFile.getSeqsAsArray());
347   
348  510 alignFile.addAnnotations(al);
349   
350  510 alignFile.addGroups(al);
351   
352  510 return al;
353    }
354   
355    /**
356    * create an alignment flatfile from a Jalview alignment view
357    *
358    * @param format
359    * @param jvsuffix
360    * @param av
361    * @param selectedOnly
362    * @return flatfile in a string
363    */
 
364  1 toggle public String formatSequences(FileFormatI format, boolean jvsuffix,
365    AlignmentViewPanel ap, boolean selectedOnly)
366    {
367   
368  1 AlignmentView selvew = ap.getAlignViewport()
369    .getAlignmentView(selectedOnly, false);
370  1 AlignmentI aselview = selvew
371    .getVisibleAlignment(ap.getAlignViewport().getGapCharacter());
372  1 List<AlignmentAnnotation> ala = (ap.getAlignViewport()
373    .getVisibleAlignmentAnnotation(selectedOnly));
374  1 if (ala != null)
375    {
376  1 for (AlignmentAnnotation aa : ala)
377    {
378  4 aselview.addAnnotation(aa);
379    }
380    }
381  1 viewpanel = ap;
382  1 return formatSequences(format, aselview, jvsuffix);
383    }
384   
385    /**
386    * Construct an output class for an alignment in a particular filetype TODO:
387    * allow caller to detect errors and warnings encountered when generating
388    * output
389    *
390    * @param format
391    * string name of alignment format
392    * @param alignment
393    * the alignment to be written out
394    * @param jvsuffix
395    * passed to AlnFile class controls whether /START-END is added to
396    * sequence names
397    *
398    * @return alignment flat file contents
399    */
 
400  177 toggle public String formatSequences(FileFormatI format, AlignmentI alignment,
401    boolean jvsuffix)
402    {
403  177 try
404    {
405  177 AlignmentFileWriterI afile = format.getWriter(alignment);
406   
407  177 afile.setNewlineString(newline);
408  177 afile.setExportSettings(exportSettings);
409  177 afile.configureForView(viewpanel);
410   
411    // check whether we were given a specific alignment to export, rather than
412    // the one in the viewpanel
413  177 SequenceI[] seqs = null;
414  177 if (viewpanel == null || viewpanel.getAlignment() == null
415    || viewpanel.getAlignment() != alignment)
416    {
417  50 seqs = alignment.getSequencesArray();
418    }
419    else
420    {
421  127 seqs = viewpanel.getAlignment().getSequencesArray();
422    }
423   
424  177 String afileresp = afile.print(seqs, jvsuffix);
425  177 if (afile.hasWarningMessage())
426    {
427  0 jalview.bin.Console.errPrintln("Warning raised when writing as "
428    + format + " : " + afile.getWarningMessage());
429    }
430  177 return afileresp;
431    } catch (Exception e)
432    {
433  0 jalview.bin.Console.errPrintln("Failed to write alignment as a '"
434    + format.getName() + "' file\n");
435  0 e.printStackTrace();
436    }
437   
438  0 return null;
439    }
440   
441    /**
442    * Determines the protocol (i.e DataSourceType.{FILE|PASTE|URL}) for the input
443    * data
444    *
445    * BH 2018 allows File or String, and can return RELATIVE_URL
446    *
447    * @param dataObject
448    * File or String
449    * @return the protocol for the input data
450    */
 
451  346 toggle public static DataSourceType checkProtocol(Object dataObject)
452    {
453  346 if (dataObject instanceof File)
454    {
455  0 return DataSourceType.FILE;
456    }
457   
458  346 String data = dataObject.toString();
459  346 DataSourceType protocol = DataSourceType.PASTE;
460  346 String ft = data.toLowerCase(Locale.ROOT).trim();
461  346 if (ft.indexOf("http:") == 0 || ft.indexOf("https:") == 0
462    || ft.indexOf("file:") == 0)
463    {
464  0 protocol = DataSourceType.URL;
465    }
466  346 else if (Platform.isJS())
467    {
468  0 protocol = DataSourceType.RELATIVE_URL;
469    }
470  346 else if (new File(data).exists())
471    {
472  334 protocol = DataSourceType.FILE;
473    }
474  346 return protocol;
475    }
476   
477    /**
478    * @param args
479    * @j2sIgnore
480    */
 
481  0 toggle public static void main(String[] args)
482    {
483  0 int i = 0;
484  0 while (i < args.length)
485    {
486  0 File f = new File(args[i]);
487  0 if (f.exists())
488    {
489  0 try
490    {
491  0 jalview.bin.Console.outPrintln("Reading file: " + f);
492  0 AppletFormatAdapter afa = new AppletFormatAdapter();
493  0 Runtime r = Runtime.getRuntime();
494  0 System.gc();
495  0 long memf = -r.totalMemory() + r.freeMemory();
496  0 long t1 = -System.currentTimeMillis();
497  0 AlignmentI al = afa.readFile(args[i], DataSourceType.FILE,
498    new IdentifyFile().identify(args[i],
499    DataSourceType.FILE));
500  0 t1 += System.currentTimeMillis();
501  0 System.gc();
502  0 memf += r.totalMemory() - r.freeMemory();
503  0 if (al != null)
504    {
505  0 jalview.bin.Console.outPrintln("Alignment contains "
506    + al.getHeight() + " sequences and " + al.getWidth()
507    + " columns.");
508  0 try
509    {
510  0 jalview.bin.Console.outPrintln(new AppletFormatAdapter()
511    .formatSequences(FileFormat.Fasta, al, true));
512    } catch (Exception e)
513    {
514  0 jalview.bin.Console.errPrintln(
515    "Couln't format the alignment for output as a FASTA file.");
516  0 e.printStackTrace(System.err);
517    }
518    }
519    else
520    {
521  0 jalview.bin.Console.outPrintln("Couldn't read alignment");
522    }
523  0 jalview.bin.Console
524    .outPrintln("Read took " + (t1 / 1000.0) + " seconds.");
525  0 jalview.bin.Console.outPrintln(
526    "Difference between free memory now and before is "
527    + (memf / (1024.0 * 1024.0) * 1.0) + " MB");
528    } catch (Exception e)
529    {
530  0 jalview.bin.Console.errPrintln("Exception when dealing with " + i
531    + "'th argument: " + args[i] + "\n" + e);
532    }
533    }
534    else
535    {
536  0 jalview.bin.Console.errPrintln("Ignoring argument '" + args[i]
537    + "' (" + i + "'th)- not a readable file.");
538    }
539  0 i++;
540    }
541    }
542   
543    /**
544    * try to discover how to access the given file as a valid datasource that
545    * will be identified as the given type.
546    *
547    * @param file
548    * @param format
549    * @return protocol that yields the data parsable as the given type
550    */
 
551  0 toggle public static DataSourceType resolveProtocol(String file,
552    FileFormatI format)
553    {
554  0 return resolveProtocol(file, format, false);
555    }
556   
 
557  0 toggle public static DataSourceType resolveProtocol(String file,
558    FileFormatI format, boolean debug)
559    {
560    // TODO: test thoroughly!
561  0 DataSourceType protocol = null;
562  0 if (debug)
563    {
564  0 jalview.bin.Console
565    .outPrintln("resolving datasource started with:\n>>file\n"
566    + file + ">>endfile");
567    }
568   
569    // This might throw a security exception in certain browsers
570    // Netscape Communicator for instance.
571  0 try
572    {
573  0 boolean rtn = false;
574  0 InputStream is = System.getSecurityManager().getClass()
575    .getResourceAsStream("/" + file);
576  0 if (is != null)
577    {
578  0 rtn = true;
579  0 is.close();
580    }
581  0 if (debug)
582    {
583  0 jalview.bin.Console.errPrintln("Resource '" + file + "' was "
584  0 + (rtn ? "" : "not") + " located by classloader.");
585    }
586  0 if (rtn)
587    {
588  0 protocol = DataSourceType.CLASSLOADER;
589    }
590   
591    } catch (Exception ex)
592    {
593  0 System.err
594    .println("Exception checking resources: " + file + " " + ex);
595    }
596   
597  0 if (file.indexOf("://") > -1)
598    {
599  0 protocol = DataSourceType.URL;
600    }
601    else
602    {
603    // skipping codebase prepend check.
604  0 protocol = DataSourceType.FILE;
605    }
606  0 FileParse fp = null;
607  0 try
608    {
609  0 if (debug)
610    {
611  0 jalview.bin.Console.outPrintln(
612    "Trying to get contents of resource as " + protocol + ":");
613    }
614  0 fp = new FileParse(file, protocol);
615  0 if (!fp.isValid())
616    {
617  0 fp = null;
618    }
619    else
620    {
621  0 if (debug)
622    {
623  0 jalview.bin.Console.outPrintln("Successful.");
624    }
625    }
626    } catch (Exception e)
627    {
628  0 if (debug)
629    {
630  0 jalview.bin.Console
631    .errPrintln("Exception when accessing content: " + e);
632    }
633  0 fp = null;
634    }
635  0 if (fp == null)
636    {
637  0 if (debug)
638    {
639  0 jalview.bin.Console.outPrintln("Accessing as paste.");
640    }
641  0 protocol = DataSourceType.PASTE;
642  0 fp = null;
643  0 try
644    {
645  0 fp = new FileParse(file, protocol);
646  0 if (!fp.isValid())
647    {
648  0 fp = null;
649    }
650    } catch (Exception e)
651    {
652  0 jalview.bin.Console
653    .errPrintln("Failed to access content as paste!");
654  0 e.printStackTrace();
655  0 fp = null;
656    }
657    }
658  0 if (fp == null)
659    {
660  0 return null;
661    }
662  0 if (format == null)
663    {
664  0 return protocol;
665    }
666    else
667    {
668  0 try
669    {
670  0 FileFormatI idformat = new IdentifyFile().identify(file, protocol);
671  0 if (idformat == null)
672    {
673  0 if (debug)
674    {
675  0 jalview.bin.Console.outPrintln(
676    "Format not identified. Inaccessible file.");
677    }
678  0 return null;
679    }
680  0 if (debug)
681    {
682  0 jalview.bin.Console.outPrintln("Format identified as " + idformat
683    + "and expected as " + format);
684    }
685  0 if (idformat.equals(format))
686    {
687  0 if (debug)
688    {
689  0 jalview.bin.Console
690    .outPrintln("Protocol identified as " + protocol);
691    }
692  0 return protocol;
693    }
694    else
695    {
696  0 if (debug)
697    {
698  0 System.out
699    .println("File deemed not accessible via " + protocol);
700    }
701  0 fp.close();
702  0 return null;
703    }
704    } catch (Exception e)
705    {
706  0 if (debug)
707    {
708  0 jalview.bin.Console
709    .errPrintln("File deemed not accessible via " + protocol);
710  0 e.printStackTrace();
711    }
712    }
713    }
714  0 return null;
715    }
716   
 
717  324 toggle public AlignmentFileReaderI getAlignFile()
718    {
719  324 return alignFile;
720    }
721    }