Merge branch 'develop' into bug/JAL-2255_seq-fetcher-broken-on-linux
[jalview.git] / src / jalview / io / FileFormats.java
diff --git a/src/jalview/io/FileFormats.java b/src/jalview/io/FileFormats.java
new file mode 100644 (file)
index 0000000..19a61cf
--- /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 capable of being identified by IdentifyFile 
+   */
+  private static Set<FileFormatI> identifiable;
+
+  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>();
+    identifiable = new HashSet<FileFormatI>();
+    for (FileFormat format : FileFormat.values())
+    {
+      registerFileFormat(format, format.isIdentifiable());
+    }
+  }
+
+  /**
+   * Answers true if the format is one that can be identified by IdentifyFile.
+   * Answers false for a null value.
+   */
+  public boolean isIdentifiable(FileFormatI f)
+  {
+    return identifiable.contains(f);
+  }
+
+  /**
+   * Registers a file format for case-insensitive lookup by name
+   * 
+   * @param format
+   */
+  public void registerFileFormat(FileFormatI format)
+  {
+    boolean isIdentifiable = format instanceof FileFormat
+            && ((FileFormat) format).isIdentifiable();
+    registerFileFormat(format, isIdentifiable);
+  }
+
+  protected void registerFileFormat(FileFormatI format,
+          boolean isIdentifiable)
+  {
+    String name = format.getName().toUpperCase();
+    if (formats.containsKey(name))
+    {
+      System.err.println("Overwriting file format: " + format.getName());
+    }
+    formats.put(name, format);
+    if (isIdentifiable)
+    {
+      identifiable.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());
+    identifiable.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();
+  }
+}