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