JAL-2344 FileFormats singleton for formats, FileFormatI simplified
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 11 Jan 2017 16:05:41 +0000 (16:05 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 11 Jan 2017 16:05:41 +0000 (16:05 +0000)
25 files changed:
src/jalview/appletgui/APopupMenu.java
src/jalview/appletgui/AlignFrame.java
src/jalview/bin/JalviewLite.java
src/jalview/bin/JalviewLiteURLRetrieve.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/CutAndPasteTransfer.java
src/jalview/gui/Desktop.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/Preferences.java
src/jalview/io/AppletFormatAdapter.java
src/jalview/io/FileFormat.java
src/jalview/io/FileFormatI.java
src/jalview/io/FileFormats.java [new file with mode: 0644]
src/jalview/io/FileLoader.java
src/jalview/io/FormatAdapter.java
src/jalview/io/JalviewFileChooser.java
src/jalview/io/JalviewFileView.java
src/jalview/jbgui/GAlignFrame.java
src/jalview/ws/jws1/JPredThread.java
src/jalview/ws/rest/params/Alignment.java
test/jalview/io/FileFormatsTest.java [new file with mode: 0644]
test/jalview/io/FormatAdapterTest.java
test/jalview/ws/jabaws/DisorderAnnotExportImport.java
test/jalview/ws/jabaws/JpredJabaStructExportImport.java
test/jalview/ws/jabaws/RNAStructExportImport.java

index 6e5f130..8f7a15b 100644 (file)
@@ -36,7 +36,8 @@ import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.io.AppletFormatAdapter;
 import jalview.io.DataSourceType;
-import jalview.io.FileFormat;
+import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.SequenceAnnotationReport;
 import jalview.schemes.Blosum62ColourScheme;
 import jalview.schemes.BuriedColourScheme;
@@ -216,7 +217,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
       e.printStackTrace();
     }
 
-    for (String ff : FileFormat.getWritableFormats(true))
+    for (String ff : FileFormats.getInstance().getWritableFormats(true))
     {
       MenuItem item = new MenuItem(ff);
 
@@ -789,7 +790,8 @@ public class APopupMenu extends java.awt.PopupMenu implements
     // now returns a full copy of sequence data
     // TODO consider using getSequenceSelection instead here
 
-    FileFormat fileFormat = FileFormat.valueOf(e.getActionCommand());
+    FileFormatI fileFormat = FileFormats.getInstance().forName(
+            e.getActionCommand());
     cap.setText(new AppletFormatAdapter().formatSequences(fileFormat,
             ap.av.getShowJVSuffix(), ap, true));
 
index 175b171..86dc19b 100644 (file)
@@ -52,6 +52,8 @@ import jalview.io.AppletFormatAdapter;
 import jalview.io.DataSourceType;
 import jalview.io.FeaturesFile;
 import jalview.io.FileFormat;
+import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.TCoffeeScoreFile;
 import jalview.schemes.Blosum62ColourScheme;
 import jalview.schemes.BuriedColourScheme;
@@ -1362,7 +1364,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
             "label.alignment_output_command",
             new Object[] { e.getActionCommand() }), 600, 500);
 
-    FileFormat fileFormat = FileFormat.valueOf(e.getActionCommand());
+    FileFormatI fileFormat = FileFormats.getInstance().forName(
+            e.getActionCommand());
     cap.setText(new AppletFormatAdapter(alignPanel).formatSequences(
             fileFormat, viewport.getAlignment(),
             viewport.getShowJVSuffix()));
@@ -3239,7 +3242,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     inputText.addActionListener(this);
     Menu outputTextboxMenu = new Menu(
             MessageManager.getString("label.out_to_textbox"));
-    for (String ff : FileFormat.getWritableFormats(true))
+    for (String ff : FileFormats.getInstance().getWritableFormats(true))
     {
       MenuItem item = new MenuItem(ff);
 
index de011ea..d7b064a 100644 (file)
@@ -38,8 +38,8 @@ import jalview.datamodel.SequenceI;
 import jalview.io.AnnotationFile;
 import jalview.io.AppletFormatAdapter;
 import jalview.io.DataSourceType;
-import jalview.io.FileFormat;
 import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.FileParse;
 import jalview.io.IdentifyFile;
 import jalview.io.JPredFile;
@@ -517,7 +517,7 @@ public class JalviewLite extends Applet implements
   {
     try
     {
-      FileFormatI theFormat = FileFormat.valueOf(format);
+      FileFormatI theFormat = FileFormats.getInstance().forName(format);
       boolean seqlimits = suffix.equalsIgnoreCase(TRUE);
       if (alf.viewport.getSelectionGroup() != null)
       {
@@ -715,7 +715,7 @@ public class JalviewLite extends Applet implements
     {
       boolean seqlimits = suffix.equalsIgnoreCase(TRUE);
 
-      FileFormatI theFormat = FileFormat.valueOf(format);
+      FileFormatI theFormat = FileFormats.getInstance().forName(format);
       String reply = new AppletFormatAdapter().formatSequences(theFormat,
               alf.viewport.getAlignment(), seqlimits);
       return reply;
index 156e146..d6fb090 100644 (file)
@@ -25,6 +25,7 @@ import jalview.io.AppletFormatAdapter;
 import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
 import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.FileParse;
 import jalview.io.IdentifyFile;
 
@@ -115,7 +116,8 @@ public class JalviewLiteURLRetrieve extends Applet
                 + " cannot be read with protocol==" + protocol);
         return;
       }
-      FileFormatI format = FileFormat.valueOf(getParameter("format"));
+      FileFormatI format = FileFormats.getInstance().forName(
+              getParameter("format"));
       if (format == null)
       {
         format = new IdentifyFile().identify(file, protocol);
index df2a742..370e649 100644 (file)
@@ -66,6 +66,7 @@ import jalview.io.BioJsHTMLOutput;
 import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
 import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.FileLoader;
 import jalview.io.FormatAdapter;
 import jalview.io.HtmlSvgOutput;
@@ -131,6 +132,8 @@ import java.awt.print.PageFormat;
 import java.awt.print.PrinterJob;
 import java.beans.PropertyChangeEvent;
 import java.io.File;
+import java.io.FileWriter;
+import java.io.PrintWriter;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -1115,7 +1118,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   public void saveAs_actionPerformed(ActionEvent e)
   {
     String format = currentFileFormat == null ? null : currentFileFormat
-            .toString();
+            .getName();
     JalviewFileChooser chooser = JalviewFileChooser.forWrite(
             Cache.getProperty("LAST_DIRECTORY"), format);
 
@@ -1149,8 +1152,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
       fileName = chooser.getSelectedFile().getPath();
 
-      Cache.setProperty("DEFAULT_FILE_FORMAT",
-              currentFileFormat.toString());
+      Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName());
 
       Cache.setProperty("LAST_DIRECTORY", fileName);
       saveAlignment(fileName, currentFileFormat);
@@ -1180,17 +1182,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
     else
     {
-      // if (!jalview.io.AppletFormatAdapter.isValidFormat(format, true))
-      // {
-      // warningMessage("Cannot save file " + fileName + " using format "
-      // + format, "Alignment output format not supported");
-      // if (!Jalview.isHeadlessMode())
-      // {
-      // saveAs_actionPerformed(null);
-      // }
-      // return false;
-      // }
-
       AlignmentExportData exportData = getAlignmentForExport(format,
               viewport, null);
       if (exportData.getSettings().isCancelled())
@@ -1215,15 +1206,14 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       {
         try
         {
-          java.io.PrintWriter out = new java.io.PrintWriter(
-                  new java.io.FileWriter(file));
+          PrintWriter out = new PrintWriter(new FileWriter(file));
 
           out.print(output);
           out.close();
           this.setTitle(file);
           statusBar.setText(MessageManager.formatMessage(
                   "label.successfully_saved_to_file_in_format",
-                  new Object[] { fileName, format }));
+                  new Object[] { fileName, format.getName() }));
         } catch (Exception ex)
         {
           success = false;
@@ -1268,8 +1258,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   protected void outputText_actionPerformed(ActionEvent e)
   {
-
-    FileFormatI fileFormat = FileFormat.forName(e.getActionCommand());
+    FileFormatI fileFormat = FileFormats.getInstance().forName(
+            e.getActionCommand());
     AlignmentExportData exportData = getAlignmentForExport(fileFormat,
             viewport, null);
     if (exportData.getSettings().isCancelled())
index df0142c..a81c998 100644 (file)
@@ -233,7 +233,7 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
       if (!Jalview.isHeadlessMode())
       {
         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
-                AppletFormatAdapter.SUPPORTED_FORMATS,
+                AppletFormatAdapter.getSupportedFormats(),
                 MessageManager.getString("label.couldnt_read_data"),
                 JvOptionPane.WARNING_MESSAGE);
       }
@@ -262,7 +262,7 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
     {
       String title = MessageManager.formatMessage(
               "label.input_cut_paste_params",
-              new String[] { format.toString() });
+              new String[] { format.getName() });
       FeatureSettingsModelI proxyColourScheme = source
               .getFeatureColourScheme();
 
@@ -340,7 +340,7 @@ public class CutAndPasteTransfer extends GCutAndPasteTransfer
       if (!Jalview.isHeadlessMode())
       {
         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
-                AppletFormatAdapter.SUPPORTED_FORMATS,
+                AppletFormatAdapter.getSupportedFormats(),
                 MessageManager.getString("label.couldnt_read_data"),
                 JvOptionPane.WARNING_MESSAGE);
       }
index ac957d8..c09adea 100644 (file)
@@ -31,6 +31,7 @@ import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
 import jalview.io.FileFormatException;
 import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.FileLoader;
 import jalview.io.IdentifyFile;
 import jalview.io.JalviewFileChooser;
@@ -1025,13 +1026,15 @@ public class Desktop extends jalview.jbgui.GDesktop implements
       Cache.setProperty("LAST_DIRECTORY", chooser
               .getSelectedFile().getParent());
 
-      FileFormatI format = null;
-      FileFormatI selectedFormat = chooser.getSelectedFormat();
-      if (FileFormat.Jalview.equals(selectedFormat))
-      {
-        format = FileFormat.Jalview;
-      }
-      else
+      FileFormatI format = chooser.getSelectedFormat();
+
+      /*
+       * Call IdentifyFile to verify the file contains what its extension implies.
+       * Skip this step for dynamically added file formats, because
+       * IdentifyFile does not know how to recognise them.
+       */
+      boolean dynamicFormat = FileFormats.getInstance().isDynamic(format);
+      if (!dynamicFormat && !FileFormat.Jalview.equals(format))
       {
         try
         {
index a93c92e..e36204c 100644 (file)
@@ -38,8 +38,8 @@ import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
-import jalview.io.FileFormat;
 import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.FormatAdapter;
 import jalview.io.SequenceAnnotationReport;
 import jalview.schemes.AnnotationColourGradient;
@@ -254,7 +254,7 @@ public class PopupMenu extends JPopupMenu
     colours.add(purinePyrimidineColour);
     colours.add(RNAInteractionColour);
 
-    for (String ff : FileFormat.getWritableFormats(true))
+    for (String ff : FileFormats.getInstance().getWritableFormats(true))
     {
       JMenuItem item = new JMenuItem(ff);
 
@@ -2279,7 +2279,8 @@ public class PopupMenu extends JPopupMenu
     // or we simply trust the user wants
     // wysiwig behaviour
 
-    FileFormatI fileFormat = FileFormat.forName(e.getActionCommand());
+    FileFormatI fileFormat = FileFormats.getInstance().forName(
+            e.getActionCommand());
     cap.setText(new FormatAdapter(ap).formatSequences(fileFormat, ap, true));
   }
 
index 0b65c1b..422745a 100755 (executable)
@@ -701,7 +701,7 @@ public class Preferences extends GPreferences
       if (format != null)
       {
         Cache.applicationProperties.setProperty("DEFAULT_FILE_FORMAT",
-                format.toString());
+                format.getName());
       }
       startupFileTextfield.setText(chooser.getSelectedFile()
               .getAbsolutePath());
index 45d65d6..1bb7ba3 100755 (executable)
@@ -77,9 +77,16 @@ public class AppletFormatAdapter
 
   public static String INVALID_CHARACTERS = "Contains invalid characters";
 
-  public static String SUPPORTED_FORMATS = "Formats currently supported are\n"
-          + prettyPrint(FileFormat.getReadableFormats());
-
+  /**
+   * Returns an error message with a list of supported readable file formats
+   * 
+   * @return
+   */
+  public static String getSupportedFormats()
+  {
+    return "Formats currently supported are\n"
+          + prettyPrint(FileFormats.getInstance().getReadableFormats());
+  }
   public AppletFormatAdapter()
   {
   }
@@ -157,7 +164,7 @@ public class AppletFormatAdapter
         }
         else
         {
-          // todo is MCview parsing obsolete yet?
+          // todo is MCview parsing obsolete yet? JAL-2120
           StructureImportSettings.setShowSeqFeatures(true);
           alignFile = new MCview.PDBfile(annotFromStructure,
                   localSecondaryStruct, serviceSecondaryStruct, inFile,
@@ -168,7 +175,9 @@ public class AppletFormatAdapter
       }
       else
       {
-        alignFile = fileFormat.getAlignmentFile(inFile, sourceType);
+        // alignFile = fileFormat.getAlignmentFile(inFile, sourceType);
+        alignFile = fileFormat.getReader(new FileParse(inFile,
+                sourceType));
       }
       return buildAlignmentFromFile();
     } catch (Exception e)
@@ -208,7 +217,7 @@ public class AppletFormatAdapter
         throw new IOException(e.getMessage());
       }
     }
-    throw new FileFormatException(SUPPORTED_FORMATS);
+    throw new FileFormatException(getSupportedFormats());
   }
 
   /**
@@ -248,7 +257,7 @@ public class AppletFormatAdapter
       }
       else
       {
-        alignFile = format.getAlignmentFile(source);
+        alignFile = format.getReader(source);
       }
 
       return buildAlignmentFromFile();
@@ -287,7 +296,7 @@ public class AppletFormatAdapter
       }
 
       // If we get to this stage, the format was not supported
-      throw new FileFormatException(SUPPORTED_FORMATS);
+      throw new FileFormatException(getSupportedFormats());
     }
   }
 
@@ -361,7 +370,7 @@ public class AppletFormatAdapter
   {
     try
     {
-      AlignmentFileI afile = format.getAlignmentFile(alignment);
+      AlignmentFileI afile = format.getWriter(alignment);
 
       afile.setNewlineString(newline);
       afile.setExportSettings(exportSettings);
@@ -389,7 +398,8 @@ public class AppletFormatAdapter
       return afileresp;
     } catch (Exception e)
     {
-      System.err.println("Failed to write alignment as a '" + format
+      System.err.println("Failed to write alignment as a '"
+              + format.getName()
               + "' file\n");
       e.printStackTrace();
     }
index 5f441d2..6d7042d 100644 (file)
@@ -6,31 +6,19 @@ import jalview.ext.jmol.JmolParser;
 import jalview.structure.StructureImportSettings;
 
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
 
 public enum FileFormat implements FileFormatI
 {
   Fasta("Fasta", "fa, fasta, mfa, fastq", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new FastaFile(inFile, sourceType);
-    }
-
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return new FastaFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new FastaFile();
     }
@@ -38,21 +26,13 @@ public enum FileFormat implements FileFormatI
   Pfam("PFAM", "pfam", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new PfamFile(inFile, sourceType);
-    }
-
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return new PfamFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new PfamFile();
     }
@@ -60,20 +40,13 @@ public enum FileFormat implements FileFormatI
   Stockholm("Stockholm", "sto,stk", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new StockholmFile(inFile, sourceType);
-    }
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return new StockholmFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new StockholmFile(al);
     }
@@ -83,20 +56,13 @@ public enum FileFormat implements FileFormatI
   PIR("PIR", "pir", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new PIRFile(inFile, sourceType);
-    }
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return new PIRFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new PIRFile();
     }
@@ -104,19 +70,13 @@ public enum FileFormat implements FileFormatI
   BLC("BLC", "BLC", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new BLCFile(inFile, sourceType);
-    }    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return new BLCFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new BLCFile();
     }
@@ -124,21 +84,13 @@ public enum FileFormat implements FileFormatI
   AMSA("AMSA", "amsa", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new AMSAFile(inFile, sourceType);
-    }
-
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return new AMSAFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new AMSAFile(al);
     }
@@ -146,19 +98,13 @@ public enum FileFormat implements FileFormatI
   Html("HTML", "html", true, false)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new HtmlFile(inFile, sourceType);
-    }    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return new HtmlFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new HtmlFile();
     }
@@ -173,40 +119,28 @@ public enum FileFormat implements FileFormatI
   Rnaml("RNAML", "xml,rnaml", true, false)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new RnamlFile(inFile, sourceType);
-    }    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return new RnamlFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new RnamlFile();
     }
 
   },
-  Json("JSON","json", true, true)
+  Json("JSON", "json", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new JSONFile(inFile, sourceType);
-    }    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return new JSONFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new JSONFile();
     }
@@ -221,19 +155,13 @@ public enum FileFormat implements FileFormatI
   Pileup("PileUp", "pileup", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new PileUpfile(inFile, sourceType);
-    }    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return new PileUpfile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new PileUpfile();
     }
@@ -242,19 +170,13 @@ public enum FileFormat implements FileFormatI
   MSF("MSF", "msf", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new MSFfile(inFile, sourceType);
-    }    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return new MSFfile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new MSFfile();
     }
@@ -263,19 +185,13 @@ public enum FileFormat implements FileFormatI
   Clustal("Clustal", "aln", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new ClustalFile(inFile, sourceType);
-    }    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return new ClustalFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new ClustalFile();
     }
@@ -283,21 +199,13 @@ public enum FileFormat implements FileFormatI
   Phylip("PHYLIP", "phy", true, true)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new PhylipFile(inFile, sourceType);
-    }
-
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return new PhylipFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new PhylipFile();
     }
@@ -305,17 +213,7 @@ public enum FileFormat implements FileFormatI
   Jnet("JnetFile", "", false, false)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      JPredFile af = new JPredFile(inFile, sourceType);
-      af.removeNonSequences();
-      return af;
-    }
-
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       JPredFile af = new JPredFile(source);
       af.removeNonSequences();
@@ -323,7 +221,7 @@ public enum FileFormat implements FileFormatI
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return null; // todo is this called?
     }
@@ -332,55 +230,21 @@ public enum FileFormat implements FileFormatI
   Features("GFF or Jalview features", "gff2,gff3", true, false)
   {
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new FeaturesFile(true, inFile, sourceType);
-    }
-
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return new FeaturesFile(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new FeaturesFile();
     }
   },
   PDB("PDB", "pdb,ent", true, false)
   {
-
     @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      // TODO obtain config value from preference settings.
-      // Set value to 'true' to test PDB processing with Jmol: JAL-1213
-      boolean isParseWithJMOL = StructureImportSettings
-              .getDefaultStructureFileFormat() != PDBEntry.Type.PDB;
-      if (isParseWithJMOL)
-      {
-        return new JmolParser(inFile, sourceType);
-      }
-      else
-      {
-        StructureImportSettings.setShowSeqFeatures(true);
-        return new MCview.PDBfile(
-                StructureImportSettings.isVisibleChainAnnotation(),
-                StructureImportSettings.isProcessSecondaryStructure(),
-                StructureImportSettings.isExternalSecondaryStructure(),
-                inFile,
-                sourceType);
-      }
-    }
-
-    @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       boolean isParseWithJMOL = StructureImportSettings
               .getDefaultStructureFileFormat() != PDBEntry.Type.PDB;
@@ -400,7 +264,7 @@ public enum FileFormat implements FileFormatI
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new JmolParser(); // todo or null?
     }
@@ -413,23 +277,14 @@ public enum FileFormat implements FileFormatI
   },
   MMCif("mmCIF", "cif", true, false)
   {
-
-    @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return new JmolParser(inFile, sourceType);
-    }
-
     @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return new JmolParser(source);
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return new JmolParser(); // todo or null?
     }
@@ -442,23 +297,14 @@ public enum FileFormat implements FileFormatI
   },
   Jalview("Jalview", "jar,jvp", true, true)
   {
-
-    @Override
-    public AlignmentFileI getAlignmentFile(String inFile,
-            DataSourceType sourceType) throws IOException
-    {
-      return null;
-    }
-
     @Override
-    public AlignmentFileI getAlignmentFile(FileParse source)
-            throws IOException
+    public AlignmentFileI getReader(FileParse source) throws IOException
     {
       return null;
     }
 
     @Override
-    public AlignmentFileI getAlignmentFile(AlignmentI al)
+    public AlignmentFileI getWriter(AlignmentI al)
     {
       return null;
     }
@@ -470,19 +316,6 @@ public enum FileFormat implements FileFormatI
     }
   };
 
-  /**
-   * A lookup map of enums by upper-cased name
-   */
-  private static Map<String, FileFormat> names;
-  static
-  {
-    names = new HashMap<String, FileFormat>();
-    for (FileFormat format : FileFormat.values())
-    {
-      names.put(format.toString().toUpperCase(), format);
-    }
-  }
-
   private boolean writable;
 
   private boolean readable;
@@ -491,65 +324,12 @@ public enum FileFormat implements FileFormatI
 
   private String name;
 
-  /**
-   * Answers a list of writeable file formats (as string, corresponding to the
-   * toString() and forName() methods)
-   * 
-   * @return
-   */
-  public static List<String> getWritableFormats(boolean textOnly)
-  {
-    List<String> l = new ArrayList<String>();
-    for (FileFormatI ff : values())
-    {
-      if (ff.isWritable() && (!textOnly || ff.isTextFormat()))
-      {
-        l.add(ff.toString());
-      }
-    }
-    return l;
-  }
-
-  /**
-   * Answers a list of readable file formats (as string, corresponding to the
-   * toString() and forName() methods)
-   * 
-   * @return
-   */
-  public static List<String> getReadableFormats()
-  {
-    List<String> l = new ArrayList<String>();
-    for (FileFormatI ff : values())
-    {
-      if (ff.isReadable())
-      {
-        l.add(ff.toString());
-      }
-    }
-    return l;
-  }
-
   @Override
   public boolean isComplexAlignFile()
   {
     return false;
   }
 
-  /**
-   * Returns the file format with the given name, or null if format is null or
-   * invalid. Unlike valueOf(), this is not case-sensitive, to be kind to
-   * writers of javascript.
-   * 
-   * @param format
-   * @return
-   */
-  public static FileFormatI forName(String format)
-  {
-    // or could store format.getShortDescription().toUpperCase()
-    // in order to decouple 'given name' from enum name
-    return format == null ? null : names.get(format.toUpperCase());
-  }
-
   @Override
   public boolean isReadable()
   {
@@ -586,19 +366,17 @@ public enum FileFormat implements FileFormatI
     return extensions;
   }
 
+  /**
+   * Answers the display name of the file format (as for example shown in menu
+   * options). This name should not be locale (language) dependent.
+   */
   @Override
-  public String toString()
+  public String getName()
   {
     return name;
   }
 
   @Override
-  public AlignmentFileI getAlignmentFile()
-  {
-    return getAlignmentFile((AlignmentI) null);
-  }
-
-  @Override
   public boolean isTextFormat()
   {
     return true;
index 0593d1e..47b9103 100644 (file)
@@ -6,20 +6,19 @@ import java.io.IOException;
 
 public interface FileFormatI
 {
+  AlignmentFileI getReader(FileParse source) throws IOException;
 
-  AlignmentFileI getAlignmentFile(String inFile, DataSourceType sourceType)
-          throws IOException;
-
-  // TODO can we get rid of one of these methods?
-  AlignmentFileI getAlignmentFile(FileParse source) throws IOException;
-
-  AlignmentFileI getAlignmentFile(AlignmentI al);
-
-  AlignmentFileI getAlignmentFile();
+  AlignmentFileI getWriter(AlignmentI al);
 
   boolean isComplexAlignFile();
 
   /**
+   * Answers the display name of the file format (as for example shown in menu
+   * options). This name should not be locale (language) dependent.
+   */
+  String getName();
+
+  /**
    * Returns a comma-separated list of file extensions associated with the
    * format
    * 
@@ -29,9 +28,9 @@ public interface FileFormatI
 
   /**
    * Answers true if the format is one that Jalview can read. This implies that
-   * the format provides implementations for getAlignmentFile(FileParse) and
-   * getAlignmentFile(String, DataSourceType) which parse the data source for
-   * sequence data.
+   * the format provides an implementation for getReader which can parse a data
+   * source for sequence data. Readable formats are included in the options in
+   * the open file dialogue.
    * 
    * @return
    */
@@ -39,8 +38,9 @@ public interface FileFormatI
 
   /**
    * Answers true if the format is one that Jalview can write. This implies that
-   * the object returned by getAlignmentFile provides an implementation of the
-   * print() method.
+   * the object returned by getWriter provides an implementation of the print()
+   * method. Writable formats are included in the options in the Save As file
+   * dialogue, and the 'output to Textbox' option (if text format).
    * 
    * @return
    */
@@ -55,7 +55,7 @@ public interface FileFormatI
   boolean isTextFormat();
 
   /**
-   * Answers true if the file format is one that provides a 3D structure
+   * Answers true if the file format is one that provides 3D structure data
    * 
    * @return
    */
diff --git a/src/jalview/io/FileFormats.java b/src/jalview/io/FileFormats.java
new file mode 100644 (file)
index 0000000..a18d4e8
--- /dev/null
@@ -0,0 +1,170 @@
+package jalview.io;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A singleton registry of alignment file formats known to Jalview. On startup,
+ * the 'built-in' formats are added (from the FileFormat enum). Additional
+ * formats can be registered (or formats deregistered) programmatically, for
+ * example with a Groovy script.
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class FileFormats
+{
+  private static FileFormats instance = new FileFormats();
+
+  /*
+   * A lookup map of file formats by upper-cased name
+   */
+  private static Map<String, FileFormatI> formats;
+
+  /*
+   * Formats in this set are built in to Jalview and instantiated
+   * on startup, any others are added dynamically 
+   */
+  private static Set<FileFormatI> builtIn;
+
+  public static FileFormats getInstance()
+  {
+    return instance;
+  }
+
+  /**
+   * Private constructor registers Jalview's built-in file formats
+   */
+  private FileFormats()
+  {
+    reset();
+  }
+
+  /**
+   * Reset to just the built-in file formats packaged with Jalview. These are
+   * added (and will be shown in menus) in the order of their declaration in the
+   * FileFormat enum.
+   */
+  public synchronized void reset()
+  {
+    formats = new LinkedHashMap<String, FileFormatI>();
+    builtIn = new HashSet<FileFormatI>();
+    for (FileFormat format : FileFormat.values())
+    {
+      registerFileFormat(format, true);
+    }
+  }
+
+  /**
+   * Answers false if the format is one 'built in' to Jalview, or true if not
+   * (meaning it has been added dynamically at runtime). Only built-in formats
+   * can be validated by IdentifyFile. Answers true for a null input.
+   */
+  public boolean isDynamic(FileFormatI f)
+  {
+    return !builtIn.contains(f);
+  }
+
+  /**
+   * Registers a file format for case-insensitive lookup by name
+   * 
+   * @param format
+   */
+  public void registerFileFormat(FileFormatI format)
+  {
+    registerFileFormat(format, false);
+  }
+
+  protected void registerFileFormat(FileFormatI format,
+          boolean isBuiltIn)
+  {
+    String name = format.getName().toUpperCase();
+    if (formats.containsKey(name))
+    {
+      System.err.println("Overwriting file format: " + format.getName());
+    }
+    formats.put(name, format);
+    if (isBuiltIn)
+    {
+      builtIn.add(format);
+    }
+  }
+
+  /**
+   * Deregisters a file format so it is no longer shown in menus
+   * 
+   * @param name
+   */
+  public void deregisterFileFormat(String name)
+  {
+    FileFormatI ff = formats.remove(name.toUpperCase());
+    builtIn.remove(ff);
+  }
+
+  /**
+   * Answers a list of writeable file formats (as strings, corresponding to the
+   * getName() and forName() methods)
+   * 
+   * @param textOnly
+   *          if true, only text (not binary) formats are included
+   * @return
+   */
+  public List<String> getWritableFormats(boolean textOnly)
+  {
+    List<String> l = new ArrayList<String>();
+    for (FileFormatI ff : formats.values())
+    {
+      if (ff.isWritable() && (!textOnly || ff.isTextFormat()))
+      {
+        l.add(ff.getName());
+      }
+    }
+    return l;
+  }
+
+  /**
+   * Answers a list of readable file formats (as strings, corresponding to the
+   * getName() and forName() methods)
+   * 
+   * @return
+   */
+  public List<String> getReadableFormats()
+  {
+    List<String> l = new ArrayList<String>();
+    for (FileFormatI ff : formats.values())
+    {
+      if (ff.isReadable())
+      {
+        l.add(ff.getName());
+      }
+    }
+    return l;
+  }
+
+  /**
+   * Returns the file format with the given name, or null if format is null or
+   * invalid. This is not case-sensitive.
+   * 
+   * @param format
+   * @return
+   */
+  public FileFormatI forName(String format)
+  {
+    return format == null ? null : formats.get(format.toUpperCase());
+  }
+
+  /**
+   * Returns an iterable collection of registered file formats (in the order in
+   * which they were registered)
+   * 
+   * @return
+   */
+  public Iterable<FileFormatI> getFormats()
+  {
+    return formats.values();
+  }
+}
index 3ad74c7..f137395 100755 (executable)
@@ -237,7 +237,7 @@ public class FileLoader implements Runnable
 
     if (protocol == DataSourceType.FILE)
     {
-      Cache.setProperty("DEFAULT_FILE_FORMAT", format.toString());
+      Cache.setProperty("DEFAULT_FILE_FORMAT", format.getName());
     }
   }
 
@@ -279,7 +279,7 @@ public class FileLoader implements Runnable
                   Desktop.desktop,
                   MessageManager.getString("label.couldnt_read_data")
                           + " in " + file + "\n"
-                          + AppletFormatAdapter.SUPPORTED_FORMATS,
+                          + AppletFormatAdapter.getSupportedFormats(),
                   MessageManager.getString("label.couldnt_read_data"),
                   JvOptionPane.WARNING_MESSAGE);
         }
@@ -311,27 +311,27 @@ public class FileLoader implements Runnable
       }
       else
       {
-        String error = AppletFormatAdapter.SUPPORTED_FORMATS;
-          try
+        String error = AppletFormatAdapter.getSupportedFormats();
+        try
+        {
+          if (source != null)
           {
-            if (source != null)
-            {
-              // read from the provided source
+            // read from the provided source
             al = new FormatAdapter().readFromFile(source, format);
-            }
-            else
-            {
-
-              // open a new source and read from it
-              FormatAdapter fa = new FormatAdapter();
-              al = fa.readFile(file, protocol, format);
-              source = fa.getAlignFile(); // keep reference for later if
-                                          // necessary.
-            }
-          } catch (java.io.IOException ex)
+          }
+          else
           {
-            error = ex.getMessage();
+
+            // open a new source and read from it
+            FormatAdapter fa = new FormatAdapter();
+            al = fa.readFile(file, protocol, format);
+            source = fa.getAlignFile(); // keep reference for later if
+                                        // necessary.
           }
+        } catch (java.io.IOException ex)
+        {
+          error = ex.getMessage();
+        }
 
         if ((al != null) && (al.getHeight() > 0) && al.hasValidSequence())
         {
index 1dbfdef..ce584f2 100755 (executable)
@@ -155,84 +155,13 @@ public class FormatAdapter extends AppletFormatAdapter
    */
   public String formatSequences(FileFormatI format, SequenceI[] seqs)
   {
-    //
-    // try
-    // {
     boolean withSuffix = getCacheSuffixDefault(format);
-    return format.getAlignmentFile().print(seqs, withSuffix);
-      // null;
-      //
-      // if (format.equalsIgnoreCase("FASTA"))
-      // {
-      // afile = new FastaFile();
-      // afile.addJVSuffix(jalview.bin.Cache.getDefault("FASTA_JVSUFFIX",
-      // true));
-      // }
-      // else if (format.equalsIgnoreCase("MSF"))
-      // {
-      // afile = new MSFfile();
-      // afile.addJVSuffix(jalview.bin.Cache
-      // .getDefault("MSF_JVSUFFIX", true));
-      // }
-      // else if (format.equalsIgnoreCase("PileUp"))
-      // {
-      // afile = new PileUpfile();
-      // afile.addJVSuffix(jalview.bin.Cache.getDefault("PILEUP_JVSUFFIX",
-      // true));
-      // }
-      // else if (format.equalsIgnoreCase("CLUSTAL"))
-      // {
-      // afile = new ClustalFile();
-      // afile.addJVSuffix(jalview.bin.Cache.getDefault("CLUSTAL_JVSUFFIX",
-      // true));
-      // }
-      // else if (format.equalsIgnoreCase("BLC"))
-      // {
-      // afile = new BLCFile();
-      // afile.addJVSuffix(jalview.bin.Cache
-      // .getDefault("BLC_JVSUFFIX", true));
-      // }
-      // else if (format.equalsIgnoreCase("PIR"))
-      // {
-      // afile = new PIRFile();
-      // afile.addJVSuffix(jalview.bin.Cache
-      // .getDefault("PIR_JVSUFFIX", true));
-      // }
-      // else if (format.equalsIgnoreCase("PFAM"))
-      // {
-      // afile = new PfamFile();
-      // afile.addJVSuffix(jalview.bin.Cache.getDefault("PFAM_JVSUFFIX",
-      // true));
-      // }
-      // /*
-      // * amsa is not supported by this function - it requires an alignment
-      // * rather than a sequence vector else if
-      // (format.equalsIgnoreCase("AMSA"))
-      // * { afile = new AMSAFile(); afile.addJVSuffix(
-      // * jalview.bin.Cache.getDefault("AMSA_JVSUFFIX", true)); }
-      // */
-
-//      afile.setSeqs(seqs);
-//      String afileresp = afile.print();
-//      if (afile.hasWarningMessage())
-//      {
-//        System.err.println("Warning raised when writing as " + format
-//                + " : " + afile.getWarningMessage());
-//      }
-//      return afileresp;
-//    } catch (Exception e)
-//    {
-//      System.err.println("Failed to write alignment as a '" + format
-//              + "' file\n");
-//      e.printStackTrace();
-//    }
-//
-//    return null;
+    return format.getWriter(null).print(seqs, withSuffix);
   }
 
   public boolean getCacheSuffixDefault(FileFormatI format)
   {
-    return Cache.getDefault(format.toString() + "_JVSUFFIX", true);
+    return Cache.getDefault(format.getName() + "_JVSUFFIX", true);
   }
 
   public String formatSequences(FileFormatI format, AlignmentI alignment,
index 7ccdaa9..2a0f8b1 100755 (executable)
@@ -68,12 +68,12 @@ public class JalviewFileChooser extends JFileChooser
   {
     List<String> extensions = new ArrayList<String>();
     List<String> descs = new ArrayList<String>();
-    for (FileFormatI format : FileFormat.values())
+    for (FileFormatI format : FileFormats.getInstance().getFormats())
     {
       if (format.isReadable())
       {
         extensions.add(format.getExtensions());
-        descs.add(format.toString());
+        descs.add(format.getName());
       }
     }
     return new JalviewFileChooser(directory,
@@ -96,12 +96,12 @@ public class JalviewFileChooser extends JFileChooser
     // with a lambda expression parameter for isReadable/isWritable
     List<String> extensions = new ArrayList<String>();
     List<String> descs = new ArrayList<String>();
-    for (FileFormatI format : FileFormat.values())
+    for (FileFormatI format : FileFormats.getInstance().getFormats())
     {
       if (format.isWritable())
       {
         extensions.add(format.getExtensions());
-        descs.add(format.toString());
+        descs.add(format.getName());
       }
     }
     return new JalviewFileChooser(directory,
@@ -269,7 +269,7 @@ public class JalviewFileChooser extends JFileChooser
       format = format.substring(0, parenPos).trim();
       try
       {
-        return FileFormat.valueOf(format);
+        return FileFormats.getInstance().forName(format);
       } catch (IllegalArgumentException e)
       {
         System.err.println("Unexpected format: " + format);
index 3461110..6bfb3b9 100755 (executable)
@@ -38,9 +38,9 @@ public class JalviewFileView extends FileView
   private void loadExtensions()
   {
     extensions = new HashMap<String, String>();
-    for (FileFormatI ff : FileFormat.values())
+    for (FileFormatI ff : FileFormats.getInstance().getFormats())
     {
-      String desc = ff.toString() + " file";
+      String desc = ff.getName() + " file";
       String exts = ff.getExtensions();
       for (String ext : exts.split(","))
       {
index 981da3b..dc17397 100755 (executable)
@@ -26,7 +26,7 @@ import jalview.bin.Cache;
 import jalview.gui.JvOptionPane;
 import jalview.gui.JvSwingUtils;
 import jalview.gui.Preferences;
-import jalview.io.FileFormat;
+import jalview.io.FileFormats;
 import jalview.schemes.ColourSchemeProperty;
 import jalview.util.MessageManager;
 
@@ -245,7 +245,7 @@ public class GAlignFrame extends JInternalFrame
       setJMenuBar(alignFrameMenuBar);
 
       // dynamically fill save as menu with available formats
-      for (String ff : FileFormat.getWritableFormats(true))
+      for (String ff : FileFormats.getInstance().getWritableFormats(true))
       {
         JMenuItem item = new JMenuItem(ff);
 
index 4e5cadc..e685d00 100644 (file)
@@ -180,8 +180,8 @@ class JPredThread extends JWS1Thread implements WSClientI
         else
         {
           throw (new Exception(MessageManager.formatMessage(
-                  "exception.unknown_format_for_file", new String[] {
-                      format.toString(), result.getAligfile() })));
+                  "exception.unknown_format_for_file", new String[] { "",
+                      result.getAligfile() })));
         }
       }
       else
index 08a242d..a8258e2 100644 (file)
@@ -23,6 +23,7 @@ package jalview.ws.rest.params;
 import jalview.datamodel.AlignmentI;
 import jalview.io.FileFormat;
 import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.FormatAdapter;
 import jalview.ws.params.OptionI;
 import jalview.ws.params.simple.BooleanOption;
@@ -147,9 +148,9 @@ public class Alignment extends InputType
 
     if (tok.startsWith("format"))
     {
-      for (FileFormatI fmt : FileFormat.values())
+      for (FileFormatI fmt : FileFormats.getInstance().getFormats())
       {
-        if (fmt.isWritable() && val.equalsIgnoreCase(fmt.toString()))
+        if (fmt.isWritable() && val.equalsIgnoreCase(fmt.getName()))
         {
           format = fmt;
           return true;
@@ -157,12 +158,9 @@ public class Alignment extends InputType
       }
       warnings.append("Invalid alignment format '" + val
               + "'. Must be one of (");
-      for (FileFormatI fmt : FileFormat.values())
+      for (String fmt : FileFormats.getInstance().getWritableFormats(true))
       {
-        if (fmt.isWritable())
-        {
-          warnings.append(" " + fmt).toString();
-        }
+        warnings.append(" ").append(fmt);
       }
       warnings.append(")\n");
     }
@@ -197,28 +195,14 @@ public class Alignment extends InputType
             "Append jalview style /start-end suffix to ID", false, false,
             writeAsFile, null));
 
+    List<String> writable = FileFormats
+            .getInstance().getWritableFormats(true);
     lst.add(new Option("format", "Alignment upload format", true,
-            FileFormat.Fasta.toString(), format.toString(), getWritableFormats(),
+            FileFormat.Fasta.toString(), format.getName(), writable,
             null));
     lst.add(createMolTypeOption("type", "Sequence type", false, type, null));
 
     return lst;
   }
 
-  /**
-   * @return
-   */
-  protected List<String> getWritableFormats()
-  {
-    List<String> formats = new ArrayList<String>();
-    for (FileFormatI ff : FileFormat.values())
-    {
-      if (ff.isWritable())
-      {
-        formats.add(ff.toString());
-      }
-    }
-    return formats;
-  }
-
 }
diff --git a/test/jalview/io/FileFormatsTest.java b/test/jalview/io/FileFormatsTest.java
new file mode 100644 (file)
index 0000000..542336f
--- /dev/null
@@ -0,0 +1,156 @@
+package jalview.io;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Iterator;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+public class FileFormatsTest
+{
+  @AfterMethod()
+  public void tearDown()
+  {
+    FileFormats.getInstance().reset();
+  }
+
+  @Test(groups = "Functional")
+  public void testIsDynamic()
+  {
+    FileFormats formats = FileFormats.getInstance();
+    for (FileFormatI ff : FileFormat.values())
+    {
+      assertFalse(formats.isDynamic(ff));
+    }
+    assertTrue(formats.isDynamic(null));
+
+    /*
+     * remove and re-add a format: it is now considered 'dynamically added'
+     */
+    formats.deregisterFileFormat(FileFormat.Fasta.getName());
+    assertNull(formats.forName(FileFormat.Fasta.getName()));
+    formats.registerFileFormat(FileFormat.Fasta);
+    assertSame(FileFormat.Fasta,
+            formats.forName(FileFormat.Fasta.getName()));
+    assertTrue(formats.isDynamic(FileFormat.Fasta));
+  }
+
+  @Test(groups = "Functional")
+  public void testGetReadableFormats()
+  {
+    String expected = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview]";
+    FileFormats formats = FileFormats.getInstance();
+    assertEquals(formats.getReadableFormats().toString(), expected);
+  }
+
+  @Test(groups = "Functional")
+  public void testGetWritableFormats()
+  {
+    String expected = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP]";
+    FileFormats formats = FileFormats.getInstance();
+    assertEquals(formats.getWritableFormats(true).toString(), expected);
+    expected = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP, Jalview]";
+    assertEquals(formats.getWritableFormats(false).toString(), expected);
+  }
+
+  @Test(groups = "Functional")
+  public void testDeregisterFileFormat()
+  {
+    String writable = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP]";
+    String readable = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview]";
+    FileFormats formats = FileFormats.getInstance();
+    assertEquals(formats.getWritableFormats(true).toString(), writable);
+    assertEquals(formats.getReadableFormats().toString(), readable);
+
+    formats.deregisterFileFormat(FileFormat.Fasta.getName());
+    writable = "[PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP]";
+    readable = "[PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview]";
+    assertEquals(formats.getWritableFormats(true).toString(), writable);
+    assertEquals(formats.getReadableFormats().toString(), readable);
+
+    /*
+     * re-register the format: it gets added to the end of the list
+     */
+    formats.registerFileFormat(FileFormat.Fasta);
+    writable = "[PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP, Fasta]";
+    readable = "[PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview, Fasta]";
+    assertEquals(formats.getWritableFormats(true).toString(), writable);
+    assertEquals(formats.getReadableFormats().toString(), readable);
+  }
+
+  @Test(groups = "Functional")
+  public void testForName()
+  {
+    FileFormats formats = FileFormats.getInstance();
+    for (FileFormatI ff : FileFormat.values())
+    {
+      assertSame(ff, formats.forName(ff.getName()));
+      assertSame(ff, formats.forName(ff.getName().toUpperCase()));
+      assertSame(ff, formats.forName(ff.getName().toLowerCase()));
+    }
+    assertNull(formats.forName(null));
+    assertNull(formats.forName("rubbish"));
+  }
+
+  @Test(groups = "Functional")
+  public void testRegisterFileFormat()
+  {
+    FileFormats formats = FileFormats.getInstance();
+    assertSame(FileFormat.MMCif,
+            formats.forName(FileFormat.MMCif.getName()));
+    assertFalse(formats.isDynamic(FileFormat.MMCif));
+
+    /*
+     * deregister mmCIF format
+     */
+    formats.deregisterFileFormat(FileFormat.MMCif.getName());
+    assertNull(formats.forName(FileFormat.MMCif.getName()));
+
+    /*
+     * re-register mmCIF format
+     * it is reinstated (but now classed as 'dynamic')
+     */
+    formats.registerFileFormat(FileFormat.MMCif);
+    assertSame(FileFormat.MMCif,
+            formats.forName(FileFormat.MMCif.getName()));
+    assertTrue(formats.isDynamic(FileFormat.MMCif));
+    // repeating does nothing
+    formats.registerFileFormat(FileFormat.MMCif);
+    assertSame(FileFormat.MMCif,
+            formats.forName(FileFormat.MMCif.getName()));
+  }
+
+  @Test(groups = "Functional")
+  public void testGetFormats()
+  {
+    /*
+     * verify the list of file formats registered matches the enum values
+     */
+    FileFormats instance = FileFormats.getInstance();
+    Iterator<FileFormatI> formats = instance.getFormats()
+            .iterator();
+    FileFormatI[] builtIn = FileFormat.values();
+
+    for (FileFormatI ff : builtIn)
+    {
+      assertSame(ff, formats.next());
+    }
+    assertFalse(formats.hasNext());
+
+    /*
+     * remove the first format, check it is no longer in 
+     * the list of formats
+     */
+    String firstFormatName = instance.getFormats().iterator().next()
+            .getName();
+    instance.deregisterFileFormat(firstFormatName);
+    assertNotEquals(instance.getFormats().iterator().next().getName(),
+            firstFormatName);
+  }
+}
index 7aa5769..b500266 100644 (file)
@@ -132,7 +132,7 @@ public class FormatAdapterTest
   static Object[][] getFormats()
   {
     List<FileFormatI> both = new ArrayList<FileFormatI>();
-    for (FileFormat format : FileFormat.values())
+    for (FileFormatI format : FileFormats.getInstance().getFormats())
     {
       if (format.isReadable() && format.isWritable()
               && format.isTextFormat())
index 3573f50..2d317e4 100644 (file)
@@ -138,7 +138,7 @@ public class DisorderAnnotExportImport
   {
     try
     {
-      String aligfileout = FileFormat.Pfam.getAlignmentFile().print(
+      String aligfileout = FileFormat.Pfam.getWriter(al).print(
               al.getSequencesArray(), true);
       String anfileout = new AnnotationFile()
               .printAnnotationsForAlignment(al);
index b8fe0a3..d5b6ed1 100644 (file)
@@ -188,7 +188,7 @@ public class JpredJabaStructExportImport
     try
     {
       // what format would be appropriate for RNAalifold annotations?
-      String aligfileout = FileFormat.Pfam.getAlignmentFile().print(
+      String aligfileout = FileFormat.Pfam.getWriter(null).print(
               al.getSequencesArray(), true);
 
       String anfileout = new AnnotationFile()
index 06c803f..f1430f6 100644 (file)
@@ -201,7 +201,7 @@ public class RNAStructExportImport
     try
     {
       // what format would be appropriate for RNAalifold annotations?
-      String aligfileout = FileFormat.Pfam.getAlignmentFile().print(
+      String aligfileout = FileFormat.Pfam.getWriter(null).print(
               al.getSequencesArray(), true);
 
       String anfileout = new AnnotationFile()