import java.util.StringTokenizer;
/**
- * A singleton that provides instances of genetic code translation tables
+ * A static class that provides instances of genetic code translation tables
*
* @author gmcarstairs
* @see https://www.ncbi.nlm.nih.gov/Taxonomy/Utils/wprintgc.cgi
*/
public final class GeneticCodes
{
+
+ /**
+ * As implemented, this has to be the first table defined in the data file.
+ */
+ private static GeneticCodeI standardTable;
+
+ /**
+ *
+ * @return the standard code table (table 1)
+ */
+ public static GeneticCodeI getStandardCodeTable()
+ {
+ return (standardTable == null
+ ? standardTable = codeTables.values().iterator().next()
+ : standardTable);
+ }
+
private static final int CODON_LENGTH = 3;
private static final String QUOTE = "\"";
private static final String RESOURCE_FILE = "/GeneticCodes.dat";
- private static GeneticCodes instance = new GeneticCodes();
-
- private Map<String, String> ambiguityCodes;
+ private static final Map<String, String> ambiguityCodes;
/*
* loaded code tables, with keys in order of loading
*/
- private Map<String, GeneticCodeI> codeTables;
+ private static final Map<String, GeneticCodeI> codeTables;
- /**
- * Private constructor enforces singleton
- */
- private GeneticCodes()
+ static
{
- if (instance == null)
- {
- ambiguityCodes = new HashMap<>();
+ ambiguityCodes = new HashMap<>();
- /*
- * LinkedHashMap preserves order of addition of entries,
- * so we can assume the Standard Code Table is the first
- */
- codeTables = new LinkedHashMap<>();
- loadAmbiguityCodes(AMBIGUITY_CODES_FILE);
- loadCodes(RESOURCE_FILE);
- }
- };
+ /*
+ * LinkedHashMap preserves order of addition of entries,
+ * so we can assume the Standard Code Table is the first
+ */
+ codeTables = new LinkedHashMap<>();
+ loadAmbiguityCodes(AMBIGUITY_CODES_FILE);
+ loadCodes(RESOURCE_FILE);
+ }
/**
- * Returns the singleton instance of this class
- *
- * @return
+ * Private constructor enforces no instantiation
*/
- public static GeneticCodes getInstance()
+ private GeneticCodes()
{
- return instance;
}
/**
*
* @return
*/
- public Iterable<GeneticCodeI> getCodeTables()
+ public static Iterable<GeneticCodeI> getCodeTables()
{
return codeTables.values();
}
/**
- * Answers the code table with the given id
+ * Answers the code table with the given id -- test suite only
*
* @param id
* @return
*/
- public GeneticCodeI getCodeTable(String id)
+ public static GeneticCodeI getCodeTable(String id)
{
return codeTables.get(id);
}
/**
- * A convenience method that returns the standard code table (table 1). As
- * implemented, this has to be the first table defined in the data file.
- *
- * @return
- */
- public GeneticCodeI getStandardCodeTable()
- {
- return codeTables.values().iterator().next();
- }
-
- /**
* Loads the code tables from a data file
*/
- protected void loadCodes(String fileName)
+ private static void loadCodes(String fileName)
{
try
{
- InputStream is = getClass().getResourceAsStream(fileName);
+ InputStream is = GeneticCodes.class.getResourceAsStream(fileName);
+ if (is == null)
+ {
+ System.err.println("Resource file not found: " + fileName);
+ return;
+ }
BufferedReader dataIn = new BufferedReader(new InputStreamReader(is));
/*
} catch (IOException | NullPointerException e)
{
Cache.log.error(
- "Error reading genetic codes data file: "
+ "Error reading genetic codes data file " + fileName + ": "
+ e.getMessage());
}
+ if (codeTables.isEmpty())
+ {
+ System.err.println(
+ "No genetic code tables loaded, check format of file "
+ + fileName);
+ }
}
/**
*
* @param fileName
*/
- protected void loadAmbiguityCodes(String fileName)
+ private static void loadAmbiguityCodes(String fileName)
{
try
{
- InputStream is = getClass().getResourceAsStream(fileName);
+ InputStream is = GeneticCodes.class.getResourceAsStream(fileName);
+ if (is == null)
+ {
+ System.err.println("Resource file not found: " + fileName);
+ return;
+ }
BufferedReader dataIn = new BufferedReader(new InputStreamReader(is));
String line = "";
while (line != null)
if (line != null && !"DNA".equals(line.toUpperCase()))
{
String[] tokens = line.split("\\t");
+ if (tokens.length == 2)
+ {
ambiguityCodes.put(tokens[0].toUpperCase(),
tokens[1].toUpperCase());
+ }
+ else
+ {
+ System.err.println(
+ "Unexpected data in " + fileName + ": " + line);
+ }
}
}
} catch (IOException e)
* @return
* @throws IOException
*/
- protected String readLine(BufferedReader dataIn) throws IOException
+ private static String readLine(BufferedReader dataIn) throws IOException
{
String line = dataIn.readLine();
while (line != null && line.startsWith("#"))
* @return
* @throws IOException
*/
- protected String loadOneTable(BufferedReader dataIn) throws IOException
+ private static String loadOneTable(BufferedReader dataIn)
+ throws IOException
{
String name = null;
String id = null;
* @param name
* @param codons
*/
- protected void registerCodeTable(final String id, final String name,
+ private static void registerCodeTable(final String id, final String name,
final Map<String, String> codons)
{
codeTables.put(id, new GeneticCodeI()
* @param codeTable
* @return
*/
- protected String getAmbiguousTranslation(String codon,
+ protected static String getAmbiguousTranslation(String codon,
Map<String, String> ambiguous, GeneticCodeI codeTable)
{
if (codon.length() != CODON_LENGTH)
ambiguous.put(codon, peptide);
return peptide;
}
+
}