JAL-2089 patch broken merge to master for Release 2.10.0b1
[jalview.git] / src / jalview / io / AppletFormatAdapter.java
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 jalview.api.AlignExportSettingI;
24 import jalview.api.AlignmentViewPanel;
25 import jalview.datamodel.Alignment;
26 import jalview.datamodel.AlignmentAnnotation;
27 import jalview.datamodel.AlignmentI;
28 import jalview.datamodel.AlignmentView;
29 import jalview.datamodel.PDBEntry.Type;
30 import jalview.ext.jmol.JmolParser;
31 import jalview.structure.StructureImportSettings;
32 import jalview.util.MessageManager;
33
34 import java.io.File;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.util.List;
38
39 /**
40  * A low level class for alignment and feature IO with alignment formatting
41  * methods used by both applet and application for generating flat alignment
42  * files. It also holds the lists of magic format names that the applet and
43  * application will allow the user to read or write files with.
44  *
45  * @author $author$
46  * @version $Revision$
47  */
48 public class AppletFormatAdapter
49 {
50   private AlignmentViewPanel viewpanel;
51
52   public static String FILE = "File";
53
54   public static String URL = "URL";
55
56   public static String PASTE = "Paste";
57
58   public static String CLASSLOADER = "ClassLoader";
59
60   /**
61    * add jalview-derived non-secondary structure annotation from PDB structure
62    */
63   boolean annotFromStructure = false;
64
65   /**
66    * add secondary structure from PDB data with built-in algorithms
67    */
68   boolean localSecondaryStruct = false;
69
70   /**
71    * process PDB data with web services
72    */
73   boolean serviceSecondaryStruct = false;
74
75   private AlignFile alignFile = null;
76
77   String inFile;
78
79   /**
80    * character used to write newlines
81    */
82   protected String newline = System.getProperty("line.separator");
83
84   private AlignExportSettingI exportSettings;
85
86   /**
87    * List of valid format strings used in the isValidFormat method
88    */
89   public static final String[] READABLE_FORMATS = new String[] { "BLC",
90       "CLUSTAL", "FASTA", "MSF", "PileUp", "PIR", "PFAM", "STH", "PDB",
91       "JnetFile", "RNAML", PhylipFile.FILE_DESC, JSONFile.FILE_DESC,
92       IdentifyFile.FeaturesFile, "HTML", "mmCIF" };
93
94   /**
95    * List of readable format file extensions by application in order
96    * corresponding to READABLE_FNAMES
97    */
98   public static final String[] READABLE_EXTENSIONS = new String[] {
99       "fa, fasta, mfa, fastq", "aln", "pfam", "msf", "pir", "blc", "amsa",
100       "sto,stk", "xml,rnaml", PhylipFile.FILE_EXT, JSONFile.FILE_EXT,
101       ".gff2,gff3", "jar,jvp", HtmlFile.FILE_EXT, "cif" };
102
103   /**
104    * List of readable formats by application in order corresponding to
105    * READABLE_EXTENSIONS
106    */
107   public static final String[] READABLE_FNAMES = new String[] { "Fasta",
108       "Clustal", "PFAM", "MSF", "PIR", "BLC", "AMSA", "Stockholm", "RNAML",
109       PhylipFile.FILE_DESC, JSONFile.FILE_DESC, IdentifyFile.FeaturesFile,
110       "Jalview", HtmlFile.FILE_DESC, "mmCIF" };
111
112   /**
113    * List of valid format strings for use by callers of the formatSequences
114    * method
115    */
116   public static final String[] WRITEABLE_FORMATS = new String[] { "BLC",
117       "CLUSTAL", "FASTA", "MSF", "PileUp", "PIR", "PFAM", "AMSA", "STH",
118       PhylipFile.FILE_DESC, JSONFile.FILE_DESC };
119
120   /**
121    * List of extensions corresponding to file format types in WRITABLE_FNAMES
122    * that are writable by the application.
123    */
124   public static final String[] WRITABLE_EXTENSIONS = new String[] {
125       "fa, fasta, mfa, fastq", "aln", "pfam", "msf", "pir", "blc", "amsa",
126       "sto,stk", PhylipFile.FILE_EXT, JSONFile.FILE_EXT, "jvp" };
127
128   /**
129    * List of writable formats by the application. Order must correspond with the
130    * WRITABLE_EXTENSIONS list of formats.
131    */
132   public static final String[] WRITABLE_FNAMES = new String[] { "Fasta",
133       "Clustal", "PFAM", "MSF", "PIR", "BLC", "AMSA", "STH",
134       PhylipFile.FILE_DESC, JSONFile.FILE_DESC, "Jalview" };
135
136   public static String INVALID_CHARACTERS = "Contains invalid characters";
137
138   // TODO: make these messages dynamic
139   public static String SUPPORTED_FORMATS = "Formats currently supported are\n"
140           + prettyPrint(READABLE_FORMATS);
141
142   public AppletFormatAdapter()
143   {
144   }
145
146   public AppletFormatAdapter(AlignmentViewPanel viewpanel)
147   {
148     this.viewpanel = viewpanel;
149   }
150
151   public AppletFormatAdapter(AlignmentViewPanel alignPanel,
152           AlignExportSettingI settings)
153   {
154     viewpanel = alignPanel;
155     exportSettings = settings;
156   }
157
158   /**
159    *
160    * @param els
161    * @return grammatically correct(ish) list consisting of els elements.
162    */
163   public static String prettyPrint(String[] els)
164   {
165     StringBuffer list = new StringBuffer();
166     for (int i = 0, iSize = els.length - 1; i < iSize; i++)
167     {
168       list.append(els[i]);
169       list.append(", ");
170     }
171     list.append(" and " + els[els.length - 1] + ".");
172     return list.toString();
173   }
174
175   public void setNewlineString(String nl)
176   {
177     newline = nl;
178   }
179
180   public String getNewlineString()
181   {
182     return newline;
183   }
184
185   /**
186    * check that this format is valid for reading
187    *
188    * @param format
189    *          a format string to be compared with READABLE_FORMATS
190    * @return true if format is readable
191    */
192   public static final boolean isValidFormat(String format)
193   {
194     return isValidFormat(format, false);
195   }
196
197   /**
198    * validate format is valid for IO
199    *
200    * @param format
201    *          a format string to be compared with either READABLE_FORMATS or
202    *          WRITEABLE_FORMATS
203    * @param forwriting
204    *          when true, format is checked for containment in WRITEABLE_FORMATS
205    * @return true if format is valid
206    */
207   public static final boolean isValidFormat(String format,
208           boolean forwriting)
209   {
210     if (format == null)
211     {
212       return false;
213     }
214     boolean valid = false;
215     String[] format_list = (forwriting) ? WRITEABLE_FORMATS
216             : READABLE_FORMATS;
217     for (String element : format_list)
218     {
219       if (element.equalsIgnoreCase(format))
220       {
221         return true;
222       }
223     }
224
225     return valid;
226   }
227
228   /**
229    * Constructs the correct filetype parser for a characterised datasource
230    *
231    * @param inFile
232    *          data/data location
233    * @param type
234    *          type of datasource
235    * @param format
236    *          File format of data provided by datasource
237    *
238    * @return DOCUMENT ME!
239    */
240   public AlignmentI readFile(String inFile, String type, String format)
241           throws java.io.IOException
242   {
243     // TODO: generalise mapping between format string and io. class instances
244     // using Constructor.invoke reflection
245     this.inFile = inFile;
246     try
247     {
248       if (format.equals("FASTA"))
249       {
250         alignFile = new FastaFile(inFile, type);
251       }
252       else if (format.equals("MSF"))
253       {
254         alignFile = new MSFfile(inFile, type);
255       }
256       else if (format.equals("PileUp"))
257       {
258         alignFile = new PileUpfile(inFile, type);
259       }
260       else if (format.equals("CLUSTAL"))
261       {
262         alignFile = new ClustalFile(inFile, type);
263       }
264       else if (format.equals("BLC"))
265       {
266         alignFile = new BLCFile(inFile, type);
267       }
268       else if (format.equals("PIR"))
269       {
270         alignFile = new PIRFile(inFile, type);
271       }
272       else if (format.equals("PFAM"))
273       {
274         alignFile = new PfamFile(inFile, type);
275       }
276       else if (format.equals("JnetFile"))
277       {
278         alignFile = new JPredFile(inFile, type);
279         ((JPredFile) alignFile).removeNonSequences();
280       }
281       else if (format.equals("PDB"))
282       {
283         // TODO obtain config value from preference settings.
284         // Set value to 'true' to test PDB processing with Jmol: JAL-1213
285         boolean isParseWithJMOL = StructureImportSettings
286                 .getDefaultPDBFileParser().equalsIgnoreCase(
287                         StructureImportSettings.StructureParser.JMOL_PARSER
288                                 .toString());
289         if (isParseWithJMOL)
290         {
291           StructureImportSettings.addSettings(annotFromStructure,
292                   localSecondaryStruct, serviceSecondaryStruct);
293           alignFile = new jalview.ext.jmol.JmolParser(inFile, type);
294         }
295         else
296         {
297           StructureImportSettings.addSettings(annotFromStructure,
298                   localSecondaryStruct, serviceSecondaryStruct);
299           StructureImportSettings.setShowSeqFeatures(true);
300           alignFile = new MCview.PDBfile(annotFromStructure,
301                   localSecondaryStruct, serviceSecondaryStruct, inFile,
302                   type);
303         }
304         ((StructureFile) alignFile).setDbRefType(format);
305       }
306       else if (format.equalsIgnoreCase("mmCIF"))
307       {
308         StructureImportSettings.addSettings(annotFromStructure,
309                 localSecondaryStruct, serviceSecondaryStruct);
310         alignFile = new jalview.ext.jmol.JmolParser(inFile, type);
311         ((StructureFile) alignFile).setDbRefType(format);
312       }
313       else if (format.equals("STH"))
314       {
315         alignFile = new StockholmFile(inFile, type);
316       }
317       else if (format.equals("SimpleBLAST"))
318       {
319         alignFile = new SimpleBlastFile(inFile, type);
320       }
321       else if (format.equals(PhylipFile.FILE_DESC))
322       {
323         alignFile = new PhylipFile(inFile, type);
324       }
325       else if (format.equals(JSONFile.FILE_DESC))
326       {
327         alignFile = new JSONFile(inFile, type);
328       }
329       else if (format.equals(HtmlFile.FILE_DESC))
330       {
331         alignFile = new HtmlFile(inFile, type);
332       }
333       else if (format.equals("RNAML"))
334       {
335         alignFile = new RnamlFile(inFile, type);
336       }
337       else if (format.equals(IdentifyFile.FeaturesFile))
338       {
339         alignFile = new FeaturesFile(true, inFile, type);
340       }
341       return buildAlignmentFrom(alignFile);
342     } catch (Exception e)
343     {
344       e.printStackTrace();
345       System.err.println("Failed to read alignment using the '" + format
346               + "' reader.\n" + e);
347
348       if (e.getMessage() != null
349               && e.getMessage().startsWith(INVALID_CHARACTERS))
350       {
351         throw new java.io.IOException(e.getMessage());
352       }
353
354       // Finally test if the user has pasted just the sequence, no id
355       if (type.equalsIgnoreCase("Paste"))
356       {
357         try
358         {
359           // Possible sequence is just residues with no label
360           alignFile = new FastaFile(">UNKNOWN\n" + inFile, "Paste");
361           return buildAlignmentFrom(alignFile);
362
363         } catch (Exception ex)
364         {
365           if (ex.toString().startsWith(INVALID_CHARACTERS))
366           {
367             throw new java.io.IOException(e.getMessage());
368           }
369
370           ex.printStackTrace();
371         }
372       }
373       if (format.equalsIgnoreCase("HTML"))
374       {
375         throw new IOException(e.getMessage());
376       }
377       // If we get to this stage, the format was not supported
378       throw new java.io.IOException(SUPPORTED_FORMATS);
379     }
380   }
381
382   /**
383    * Constructs the correct filetype parser for an already open datasource
384    *
385    * @param source
386    *          an existing datasource
387    * @param format
388    *          File format of data that will be provided by datasource
389    *
390    * @return DOCUMENT ME!
391    */
392   public AlignmentI readFromFile(FileParse source, String format)
393           throws java.io.IOException
394   {
395     // TODO: generalise mapping between format string and io. class instances
396     // using Constructor.invoke reflection
397     // This is exactly the same as the readFile method except we substitute
398     // 'inFile, type' with 'source'
399     this.inFile = source.getInFile();
400     String type = source.type;
401     try
402     {
403       if (format.equals("FASTA"))
404       {
405         alignFile = new FastaFile(source);
406       }
407       else if (format.equals("MSF"))
408       {
409         alignFile = new MSFfile(source);
410       }
411       else if (format.equals("PileUp"))
412       {
413         alignFile = new PileUpfile(source);
414       }
415       else if (format.equals("CLUSTAL"))
416       {
417         alignFile = new ClustalFile(source);
418       }
419       else if (format.equals("BLC"))
420       {
421         alignFile = new BLCFile(source);
422       }
423       else if (format.equals("PIR"))
424       {
425         alignFile = new PIRFile(source);
426       }
427       else if (format.equals("PFAM"))
428       {
429         alignFile = new PfamFile(source);
430       }
431       else if (format.equals("JnetFile"))
432       {
433         alignFile = new JPredFile(source);
434         ((JPredFile) alignFile).removeNonSequences();
435       }
436       else if (format.equals("PDB"))
437       {
438         // TODO obtain config value from preference settings
439         boolean isParseWithJMOL = false;
440         if (isParseWithJMOL)
441         {
442           StructureImportSettings.addSettings(annotFromStructure,
443                   localSecondaryStruct, serviceSecondaryStruct);
444           alignFile = new JmolParser(source);
445         }
446         else
447         {
448           StructureImportSettings.setShowSeqFeatures(true);
449           alignFile = new MCview.PDBfile(annotFromStructure,
450                   localSecondaryStruct, serviceSecondaryStruct, source);
451         }
452         ((StructureFile) alignFile).setDbRefType(Type.PDB);
453       }
454       else if (format.equalsIgnoreCase("mmCIF"))
455       {
456         StructureImportSettings.addSettings(annotFromStructure,
457                 localSecondaryStruct, serviceSecondaryStruct);
458         alignFile = new JmolParser(source);
459         ((StructureFile) alignFile).setDbRefType(Type.MMCIF);
460       }
461       else if (format.equals("STH"))
462       {
463         alignFile = new StockholmFile(source);
464       }
465       else if (format.equals("RNAML"))
466       {
467         alignFile = new RnamlFile(source);
468       }
469       else if (format.equals("SimpleBLAST"))
470       {
471         alignFile = new SimpleBlastFile(source);
472       }
473       else if (format.equals(PhylipFile.FILE_DESC))
474       {
475         alignFile = new PhylipFile(source);
476       }
477       else if (format.equals(IdentifyFile.FeaturesFile))
478       {
479         alignFile = new FeaturesFile(inFile, type);
480       }
481       else if (format.equals(JSONFile.FILE_DESC))
482       {
483         alignFile = new JSONFile(source);
484       }
485       else if (format.equals(HtmlFile.FILE_DESC))
486       {
487         alignFile = new HtmlFile(source);
488       }
489
490       return buildAlignmentFrom(alignFile);
491
492     } catch (Exception e)
493     {
494       e.printStackTrace();
495       System.err.println("Failed to read alignment using the '" + format
496               + "' reader.\n" + e);
497
498       if (e.getMessage() != null
499               && e.getMessage().startsWith(INVALID_CHARACTERS))
500       {
501         throw new java.io.IOException(e.getMessage());
502       }
503
504       // Finally test if the user has pasted just the sequence, no id
505       if (type.equalsIgnoreCase("Paste"))
506       {
507         try
508         {
509           // Possible sequence is just residues with no label
510           alignFile = new FastaFile(">UNKNOWN\n" + inFile, "Paste");
511           return buildAlignmentFrom(alignFile);
512
513         } catch (Exception ex)
514         {
515           if (ex.toString().startsWith(INVALID_CHARACTERS))
516           {
517             throw new java.io.IOException(e.getMessage());
518           }
519
520           ex.printStackTrace();
521         }
522       }
523
524       // If we get to this stage, the format was not supported
525       throw new java.io.IOException(SUPPORTED_FORMATS);
526     }
527   }
528
529   /**
530    * boilerplate method to handle data from an AlignFile and construct a new
531    * alignment or import to an existing alignment
532    * 
533    * @param alignFile2
534    * @return AlignmentI instance ready to pass to a UI constructor
535    */
536   private AlignmentI buildAlignmentFrom(AlignFile alignFile2)
537   {
538     // Standard boilerplate for creating alignment from parser
539     // alignFile.configureForView(viewpanel);
540
541     AlignmentI al = new Alignment(alignFile.getSeqsAsArray());
542
543     alignFile.addAnnotations(al);
544
545     alignFile.addGroups(al);
546
547     return al;
548   }
549
550   /**
551    * create an alignment flatfile from a Jalview alignment view
552    * 
553    * @param format
554    * @param jvsuffix
555    * @param av
556    * @param selectedOnly
557    * @return flatfile in a string
558    */
559   public String formatSequences(String format, boolean jvsuffix,
560           AlignmentViewPanel ap, boolean selectedOnly)
561   {
562
563     AlignmentView selvew = ap.getAlignViewport().getAlignmentView(
564             selectedOnly, false);
565     AlignmentI aselview = selvew.getVisibleAlignment(ap.getAlignViewport()
566             .getGapCharacter());
567     List<AlignmentAnnotation> ala = (ap.getAlignViewport()
568             .getVisibleAlignmentAnnotation(selectedOnly));
569     if (ala != null)
570     {
571       for (AlignmentAnnotation aa : ala)
572       {
573         aselview.addAnnotation(aa);
574       }
575     }
576     viewpanel = ap;
577     return formatSequences(format, aselview, jvsuffix);
578   }
579
580   /**
581    * Construct an output class for an alignment in a particular filetype TODO:
582    * allow caller to detect errors and warnings encountered when generating
583    * output
584    *
585    * @param format
586    *          string name of alignment format
587    * @param alignment
588    *          the alignment to be written out
589    * @param jvsuffix
590    *          passed to AlnFile class controls whether /START-END is added to
591    *          sequence names
592    *
593    * @return alignment flat file contents
594    */
595   public String formatSequences(String format, AlignmentI alignment,
596           boolean jvsuffix)
597   {
598     try
599     {
600       AlignFile afile = null;
601       if (format.equalsIgnoreCase("FASTA"))
602       {
603         afile = new FastaFile();
604       }
605       else if (format.equalsIgnoreCase("MSF"))
606       {
607         afile = new MSFfile();
608       }
609       else if (format.equalsIgnoreCase("PileUp"))
610       {
611         afile = new PileUpfile();
612       }
613       else if (format.equalsIgnoreCase("CLUSTAL"))
614       {
615         afile = new ClustalFile();
616       }
617       else if (format.equalsIgnoreCase("BLC"))
618       {
619         afile = new BLCFile();
620       }
621       else if (format.equalsIgnoreCase("PIR"))
622       {
623         afile = new PIRFile();
624       }
625       else if (format.equalsIgnoreCase("PFAM"))
626       {
627         afile = new PfamFile();
628       }
629       else if (format.equalsIgnoreCase("STH"))
630       {
631         afile = new StockholmFile(alignment);
632       }
633       else if (format.equalsIgnoreCase("AMSA"))
634       {
635         afile = new AMSAFile(alignment);
636       }
637       else if (format.equalsIgnoreCase(PhylipFile.FILE_DESC))
638       {
639         afile = new PhylipFile();
640       }
641       else if (format.equalsIgnoreCase(JSONFile.FILE_DESC))
642       {
643         afile = new JSONFile();
644       }
645       else if (format.equalsIgnoreCase("RNAML"))
646       {
647         afile = new RnamlFile();
648       }
649
650       else
651       {
652         throw new Exception(
653                 MessageManager
654                         .getString("error.implementation_error_unknown_file_format_string"));
655       }
656
657       afile.setNewlineString(newline);
658       afile.addJVSuffix(jvsuffix);
659       afile.setExportSettings(exportSettings);
660       afile.configureForView(viewpanel);
661
662       // check whether we were given a specific alignment to export, rather than
663       // the one in the viewpanel
664       if (viewpanel == null || viewpanel.getAlignment() == null
665               || viewpanel.getAlignment() != alignment)
666       {
667         afile.setSeqs(alignment.getSequencesArray());
668       }
669       else
670       {
671         afile.setSeqs(viewpanel.getAlignment().getSequencesArray());
672       }
673
674       String afileresp = afile.print();
675       if (afile.hasWarningMessage())
676       {
677         System.err.println("Warning raised when writing as " + format
678                 + " : " + afile.getWarningMessage());
679       }
680       return afileresp;
681     } catch (Exception e)
682     {
683       System.err.println("Failed to write alignment as a '" + format
684               + "' file\n");
685       e.printStackTrace();
686     }
687
688     return null;
689   }
690
691   public static String checkProtocol(String file)
692   {
693     String protocol = FILE;
694     String ft = file.toLowerCase().trim();
695     if (ft.indexOf("http:") == 0 || ft.indexOf("https:") == 0
696             || ft.indexOf("file:") == 0)
697     {
698       protocol = URL;
699     }
700     return protocol;
701   }
702
703   public static void main(String[] args)
704   {
705     int i = 0;
706     while (i < args.length)
707     {
708       File f = new File(args[i]);
709       if (f.exists())
710       {
711         try
712         {
713           System.out.println("Reading file: " + f);
714           AppletFormatAdapter afa = new AppletFormatAdapter();
715           Runtime r = Runtime.getRuntime();
716           System.gc();
717           long memf = -r.totalMemory() + r.freeMemory();
718           long t1 = -System.currentTimeMillis();
719           AlignmentI al = afa.readFile(args[i], FILE,
720                   new IdentifyFile().identify(args[i], FILE));
721           t1 += System.currentTimeMillis();
722           System.gc();
723           memf += r.totalMemory() - r.freeMemory();
724           if (al != null)
725           {
726             System.out.println("Alignment contains " + al.getHeight()
727                     + " sequences and " + al.getWidth() + " columns.");
728             try
729             {
730               System.out.println(new AppletFormatAdapter().formatSequences(
731                       "FASTA", al, true));
732             } catch (Exception e)
733             {
734               System.err
735                       .println("Couln't format the alignment for output as a FASTA file.");
736               e.printStackTrace(System.err);
737             }
738           }
739           else
740           {
741             System.out.println("Couldn't read alignment");
742           }
743           System.out.println("Read took " + (t1 / 1000.0) + " seconds.");
744           System.out
745                   .println("Difference between free memory now and before is "
746                           + (memf / (1024.0 * 1024.0) * 1.0) + " MB");
747         } catch (Exception e)
748         {
749           System.err.println("Exception when dealing with " + i
750                   + "'th argument: " + args[i] + "\n" + e);
751         }
752       }
753       else
754       {
755         System.err.println("Ignoring argument '" + args[i] + "' (" + i
756                 + "'th)- not a readable file.");
757       }
758       i++;
759     }
760   }
761
762   /**
763    * try to discover how to access the given file as a valid datasource that
764    * will be identified as the given type.
765    *
766    * @param file
767    * @param format
768    * @return protocol that yields the data parsable as the given type
769    */
770   public static String resolveProtocol(String file, String format)
771   {
772     return resolveProtocol(file, format, false);
773   }
774
775   public static String resolveProtocol(String file, String format,
776           boolean debug)
777   {
778     // TODO: test thoroughly!
779     String protocol = null;
780     if (debug)
781     {
782       System.out.println("resolving datasource started with:\n>>file\n"
783               + file + ">>endfile");
784     }
785
786     // This might throw a security exception in certain browsers
787     // Netscape Communicator for instance.
788     try
789     {
790       boolean rtn = false;
791       InputStream is = System.getSecurityManager().getClass()
792               .getResourceAsStream("/" + file);
793       if (is != null)
794       {
795         rtn = true;
796         is.close();
797       }
798       if (debug)
799       {
800         System.err.println("Resource '" + file + "' was "
801                 + (rtn ? "" : "not") + " located by classloader.");
802       }
803       ;
804       if (rtn)
805       {
806         protocol = AppletFormatAdapter.CLASSLOADER;
807       }
808
809     } catch (Exception ex)
810     {
811       System.err
812               .println("Exception checking resources: " + file + " " + ex);
813     }
814
815     if (file.indexOf("://") > -1)
816     {
817       protocol = AppletFormatAdapter.URL;
818     }
819     else
820     {
821       // skipping codebase prepend check.
822       protocol = AppletFormatAdapter.FILE;
823     }
824     FileParse fp = null;
825     try
826     {
827       if (debug)
828       {
829         System.out.println("Trying to get contents of resource as "
830                 + protocol + ":");
831       }
832       fp = new FileParse(file, protocol);
833       if (!fp.isValid())
834       {
835         fp = null;
836       }
837       else
838       {
839         if (debug)
840         {
841           System.out.println("Successful.");
842         }
843       }
844     } catch (Exception e)
845     {
846       if (debug)
847       {
848         System.err.println("Exception when accessing content: " + e);
849       }
850       fp = null;
851     }
852     if (fp == null)
853     {
854       if (debug)
855       {
856         System.out.println("Accessing as paste.");
857       }
858       protocol = AppletFormatAdapter.PASTE;
859       fp = null;
860       try
861       {
862         fp = new FileParse(file, protocol);
863         if (!fp.isValid())
864         {
865           fp = null;
866         }
867       } catch (Exception e)
868       {
869         System.err.println("Failed to access content as paste!");
870         e.printStackTrace();
871         fp = null;
872       }
873     }
874     if (fp == null)
875     {
876       return null;
877     }
878     if (format == null || format.length() == 0)
879     {
880       return protocol;
881     }
882     else
883     {
884       try
885       {
886         String idformat = new jalview.io.IdentifyFile().identify(file,
887                 protocol);
888         if (idformat == null)
889         {
890           if (debug)
891           {
892             System.out.println("Format not identified. Inaccessible file.");
893           }
894           return null;
895         }
896         if (debug)
897         {
898           System.out.println("Format identified as " + idformat
899                   + "and expected as " + format);
900         }
901         if (idformat.equals(format))
902         {
903           if (debug)
904           {
905             System.out.println("Protocol identified as " + protocol);
906           }
907           return protocol;
908         }
909         else
910         {
911           if (debug)
912           {
913             System.out
914                     .println("File deemed not accessible via " + protocol);
915           }
916           fp.close();
917           return null;
918         }
919       } catch (Exception e)
920       {
921         if (debug)
922         {
923           System.err.println("File deemed not accessible via " + protocol);
924           e.printStackTrace();
925         }
926         ;
927
928       }
929     }
930     return null;
931   }
932
933   public AlignFile getAlignFile()
934   {
935     return alignFile;
936   }
937
938   public void setAlignFile(AlignFile alignFile)
939   {
940     this.alignFile = alignFile;
941   }
942 }