JAL-2446 merged to spike branch
[jalview.git] / src / jalview / io / FileFormats.java
1 package jalview.io;
2
3 import java.util.ArrayList;
4 import java.util.HashSet;
5 import java.util.LinkedHashMap;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.Set;
9
10 /**
11  * A singleton registry of alignment file formats known to Jalview. On startup,
12  * the 'built-in' formats are added (from the FileFormat enum). Additional
13  * formats can be registered (or formats deregistered) programmatically, for
14  * example with a Groovy script.
15  * 
16  * @author gmcarstairs
17  *
18  */
19 public class FileFormats
20 {
21   private static FileFormats instance = new FileFormats();
22
23   /*
24    * A lookup map of file formats by upper-cased name
25    */
26   private static Map<String, FileFormatI> formats;
27
28   /*
29    * Formats in this set are capable of being identified by IdentifyFile 
30    */
31   private static Set<FileFormatI> identifiable;
32
33   public static FileFormats getInstance()
34   {
35     return instance;
36   }
37
38   /**
39    * Private constructor registers Jalview's built-in file formats
40    */
41   private FileFormats()
42   {
43     reset();
44   }
45
46   /**
47    * Reset to just the built-in file formats packaged with Jalview. These are
48    * added (and will be shown in menus) in the order of their declaration in the
49    * FileFormat enum.
50    */
51   public synchronized void reset()
52   {
53     formats = new LinkedHashMap<String, FileFormatI>();
54     identifiable = new HashSet<FileFormatI>();
55     for (FileFormat format : FileFormat.values())
56     {
57       registerFileFormat(format, format.isIdentifiable());
58     }
59   }
60
61   /**
62    * Answers true if the format is one that can be identified by IdentifyFile.
63    * Answers false for a null value.
64    */
65   public boolean isIdentifiable(FileFormatI f)
66   {
67     return identifiable.contains(f);
68   }
69
70   /**
71    * Registers a file format for case-insensitive lookup by name
72    * 
73    * @param format
74    */
75   public void registerFileFormat(FileFormatI format)
76   {
77     boolean isIdentifiable = format instanceof FileFormat
78             && ((FileFormat) format).isIdentifiable();
79     registerFileFormat(format, isIdentifiable);
80   }
81
82   protected void registerFileFormat(FileFormatI format,
83           boolean isIdentifiable)
84   {
85     String name = format.getName().toUpperCase();
86     if (formats.containsKey(name))
87     {
88       System.err.println("Overwriting file format: " + format.getName());
89     }
90     formats.put(name, format);
91     if (isIdentifiable)
92     {
93       identifiable.add(format);
94     }
95   }
96
97   /**
98    * Deregisters a file format so it is no longer shown in menus
99    * 
100    * @param name
101    */
102   public void deregisterFileFormat(String name)
103   {
104     FileFormatI ff = formats.remove(name.toUpperCase());
105     identifiable.remove(ff);
106   }
107
108   /**
109    * Answers a list of writeable file formats (as strings, corresponding to the
110    * getName() and forName() methods)
111    * 
112    * @param textOnly
113    *          if true, only text (not binary) formats are included
114    * @return
115    */
116   public List<String> getWritableFormats(boolean textOnly)
117   {
118     List<String> l = new ArrayList<String>();
119     for (FileFormatI ff : formats.values())
120     {
121       if (ff.isWritable() && (!textOnly || ff.isTextFormat()))
122       {
123         l.add(ff.getName());
124       }
125     }
126     return l;
127   }
128
129   /**
130    * Answers a list of readable file formats (as strings, corresponding to the
131    * getName() and forName() methods)
132    * 
133    * @return
134    */
135   public List<String> getReadableFormats()
136   {
137     List<String> l = new ArrayList<String>();
138     for (FileFormatI ff : formats.values())
139     {
140       if (ff.isReadable())
141       {
142         l.add(ff.getName());
143       }
144     }
145     return l;
146   }
147
148   /**
149    * Returns the file format with the given name, or null if format is null or
150    * invalid. This is not case-sensitive.
151    * 
152    * @param format
153    * @return
154    */
155   public FileFormatI forName(String format)
156   {
157     return format == null ? null : formats.get(format.toUpperCase());
158   }
159
160   /**
161    * Returns an iterable collection of registered file formats (in the order in
162    * which they were registered)
163    * 
164    * @return
165    */
166   public Iterable<FileFormatI> getFormats()
167   {
168     return formats.values();
169   }
170 }