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