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