uk.ac.babraham.BamQC.Preferences.BamQCPreferences.java Source code

Java tutorial

Introduction

Here is the source code for uk.ac.babraham.BamQC.Preferences.BamQCPreferences.java

Source

/**
 * Copyright Copyright 2010-15 Simon Andrews
 *
 *    This file is part of BamQC.
 *
 *    BamQC is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    BamQC is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with BamQC; if not, write to the Free Software
 *    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
/*
 * Changelog: 
 * - Piero Dalle Pezze: Imported from SeqMonk and adjusted for BamQC
 * - Simon Andrews: Class creation.
 */
package uk.ac.babraham.BamQC.Preferences;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;

import org.apache.commons.lang3.SystemUtils;
import org.apache.log4j.Logger;

/**
 * A set of preferences, both temporary and permanent which are used
 * throughout BamQC.  Permanent preferences can be loaded from and
 * saved to a preferences file allowing persistence between sessions.
 * @author Simon Andrews
 * @author Piero Dalle Pezze
 */
public class BamQCPreferences {

    private static Logger log = Logger.getLogger(BamQCPreferences.class);

    /** The single instantiated instance of preferences */
    private static BamQCPreferences p = new BamQCPreferences();

    /** A list of annotation types not to load */
    private HashSet<String> ignoredAnnotations = new HashSet<String>();

    /** The directory under which to look for genome files */
    private File genomeBase = null;

    /** The default save location. */
    private File saveLocation = null;

    /** The last used save location. */
    private File lastUsedSaveLocation = null;

    /** The preferences file. */
    private File preferencesFile = null;

    /** The network address from where we can download new genomes */
    private String genomeDownloadLocation = "http://www.bioinformatics.babraham.ac.uk/seqmonk/genomes/";

    /** Whether we're using a network proxy */
    private boolean useProxy = false;

    /** The proxy host. */
    private String proxyHost = "";

    /** The proxy port. */
    private int proxyPort = 0;

    /** The recently opened files list */
    private LinkedList<String> recentlyOpenedFiles = new LinkedList<String>();

    /**
     * Instantiates a preferences object.  Only ever called once from inside this
     * class.  External access is via the getInstnace() method.
     */
    private BamQCPreferences() {

        //      // This code uses apache commons.lang3. If you don't want to use it, you can edit this code and use the commented code just below.
        //      if(SystemUtils.IS_OS_MAC_OSX) {
        //         // let's store these files inside a folder BamQC
        ////         preferencesFile= new File(System.getProperty("user.home") + File.separator + "Library" + File.separator + "BamQC" + File.separator + "bamqc_prefs.txt");
        //         saveLocation = new File(System.getProperty("user.home") + File.separator + "Library" + File.separator + "BamQC" + File.separator + "BamQC_files");
        //         genomeBase = new File(saveLocation.getAbsolutePath() + File.separator + "genomes");
        //      } else if (SystemUtils.IS_OS_WINDOWS) {
        //         // let's store these files inside a folder BamQC
        ////         preferencesFile= new File(System.getProperty("user.home") + File.separator + "bamqc" + File.separator + "bamqc_prefs.txt");
        //         saveLocation = new File(System.getProperty("user.home") + File.separator + "bamqc" + File.separator + "BamQC_files");
        //         genomeBase = new File(saveLocation.getAbsolutePath() + File.separator + "genomes");
        //      } else if(SystemUtils.IS_OS_UNIX) {
        //         // let's store these files as hidden files inside a folder .bamqc
        ////         preferencesFile= new File(System.getProperty("user.home") + File.separator + ".bamqc" + File.separator + "bamqc_prefs.txt");
        //         saveLocation = new File(System.getProperty("user.home") + File.separator + ".bamqc" + File.separator + "BamQC_files");
        //         genomeBase = new File(saveLocation.getAbsolutePath() + File.separator + "genomes");
        //      } else {
        //         // let's store these files explicitly inside a folder bamqc
        ////         preferencesFile= new File(System.getProperty("user.home") + File.separator + "bamqc" + File.separator + "bamqc_prefs.txt");
        //         saveLocation = new File(System.getProperty("user.home") + File.separator + "bamqc" + File.separator + "BamQC_files");
        //         genomeBase = new File(saveLocation.getAbsolutePath() + File.separator + "genomes");
        //      }

        // Code independent of apache commons.lang3
        saveLocation = new File(System.getProperty("user.home") + File.separator + File.separator + "BamQC_files");
        genomeBase = new File(saveLocation.getAbsolutePath() + File.separator + "genomes");

        // This is left outside for now. 
        preferencesFile = new File(System.getProperty("user.home") + File.separator + "bamqc_prefs.txt");

        new File(genomeBase.getAbsolutePath()).mkdirs();
        new File(saveLocation.getAbsolutePath()).mkdirs();

        if (preferencesFile != null && preferencesFile.exists()) {
            //         System.out.println("Loading preferences from file...");
            loadPreferences();
        } else {
            ignoredAnnotations.add("source");
            ignoredAnnotations.add("exon");
            ignoredAnnotations.add("sts");
            ignoredAnnotations.add("misc_feature");
            try {
                savePreferences();
            } catch (IOException e) {
                log.error(e, e);
            }
        }
        updateProxyInfo();
    }

    /**
     * Load preferences from a saved file
     */
    private void loadPreferences() {

        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(preferencesFile));

            String line;
            String[] sections;
            while ((line = br.readLine()) != null) {
                if (line.startsWith("#"))
                    continue; // It's a comment
                sections = line.split("\\t", -1);

                if (sections[0].equals("GenomeBase")) {

                    /*
                     * We used to save the genome base even if it was the same
                     * as the default genome directory in the install.  To
                     * make life easier if the install location moves we now
                     * only store this if the location is something other than
                     * the default.
                     */

                    File defaultGenomesLocation = getGenomeBase();

                    File customBase = new File(sections[1]);

                    if (!customBase.equals(defaultGenomesLocation)) {
                        genomeBase = customBase;
                    }

                } else if (sections[0].equals("SaveLocation")) {
                    saveLocation = new File(sections[1]);
                } else if (sections[0].equals("GenomeDownloadLocation")) {
                    if (sections[1].equals("http://www.bioinformatics.bbsrc.ac.uk/chipmonk/genomes/")) {
                        genomeDownloadLocation = "http://www.bioinformatics.babraham.ac.uk/seqmonk/genomes/";
                    } else {
                        genomeDownloadLocation = sections[1];
                    }
                } else if (sections[0].equals("Proxy")) {
                    proxyHost = sections[1];
                    if (sections.length > 2 && sections[2].length() > 0) {
                        proxyPort = Integer.parseInt(sections[2]);
                    }
                    if (proxyHost.length() > 0) {
                        useProxy = true;
                    }
                } else if (sections[0].equals("RecentFile")) {
                    File f = new File(sections[1]);
                    if (f.exists()) {
                        recentlyOpenedFiles.add(sections[1]);
                    }
                } else if (sections[0].equals("LoadedFeatures")) {
                    // This was present in old versions of the preferences
                    // file and is no longer used.  We'll substitute in
                    // the default set of ignored values
                    ignoredAnnotations.add("source");
                    ignoredAnnotations.add("exon");
                    ignoredAnnotations.add("sts");
                    ignoredAnnotations.add("misc_feature");
                } else if (sections[0].equals("IgnoredFeatures")) {
                    for (int i = 1; i < sections.length; i++) {
                        ignoredAnnotations.add(sections[i]);
                    }
                } else {
                    log.error("Unknown preference '" + sections[0] + "'");
                }

            }
            br.close();
        } catch (FileNotFoundException e) {
            log.error(e, e);
        } catch (IOException e) {
            log.error(e, e);
        }

    }

    /**
     * Save preferences.
     * 
     * @throws IOException 
     */
    public void savePreferences() throws IOException {
        PrintWriter p = new PrintWriter(new FileWriter(preferencesFile));

        p.println("# BamQC Preferences file.  Do not edit by hand.");

        // First write out the GenomeBase if they've specified a custom location
        if (genomeBase != null) {
            p.println("GenomeBase\t" + genomeBase.getAbsolutePath());
        }

        // Then the saveLocation
        p.println("SaveLocation\t" + saveLocation.getAbsolutePath());

        // Then the proxy information
        p.println("Proxy\t" + proxyHost + "\t" + proxyPort);

        // The genome download URL
        p.println("GenomeDownloadLocation\t" + genomeDownloadLocation);

        // Save the recently opened file list
        Iterator<String> rof = recentlyOpenedFiles.iterator();
        while (rof.hasNext()) {
            p.println("RecentFile\t" + rof.next());
        }

        // Finally the list of features to load
        StringBuilder b = new StringBuilder("IgnoredFeatures");
        Iterator<String> i = ignoredAnnotations.iterator();
        while (i.hasNext()) {
            b.append("\t");
            b.append(i.next().toLowerCase());
        }
        p.println(b);

        p.close();

    }

    /**
     * Gets the single instance of BamQCPreferences.
     * 
     * @return single instance of BamQCPreferences
     */
    public static BamQCPreferences getInstance() {
        return p;
    }

    /**
     * Gets the list of recently opened files.
     * 
     * @return the recently opened files
     */
    public String[] getRecentlyOpenedFiles() {
        return recentlyOpenedFiles.toArray(new String[0]);
    }

    /**
     * Adds a path to the recently opened files list.  We store
     * up to 5 recently used files on a rotating basis.  Adding
     * a new one pushes out the oldest one.
     * 
     * @param filePath The new file location to add
     */
    public void addRecentlyOpenedFile(String filePath) {
        // I know this is inefficient in a linked list but
        // it's only going to contain 5 elements so who cares
        if (recentlyOpenedFiles.contains(filePath)) {
            recentlyOpenedFiles.remove(filePath);
        }
        recentlyOpenedFiles.add(0, filePath);

        // Only keep 9 items
        while (recentlyOpenedFiles.size() > 9) {
            recentlyOpenedFiles.remove(9);
        }
        try {
            savePreferences();
        } catch (IOException e) {
            // In this case we don't report this error since
            // the user isn't explicitly asking us to save.
        }
    }

    /**
     * Asks whether a particular type of annotation is on the list
     * of types to exclude from loading.
     * 
     * @param type The annotation type to check
     * @return true, if this type should be loaded
     */
    public boolean loadAnnotation(String type) {
        return !ignoredAnnotations.contains(type.toLowerCase());
    }

    /**
     * Gets a list of feature types which will not be loaded
     * 
     * @return a list of ignored feature types
     */
    public String[] getIgnoredFeatures() {
        return ignoredAnnotations.toArray(new String[0]);
    }

    /**
     * Flag to say if network access should go through a proxy
     * 
     * @return true, if a proxy should be used
     */
    public boolean useProxy() {
        return useProxy;
    }

    /**
     * Proxy host.
     * 
     * @return The name of the proxy to use.  Only use this if the
     * useProxy flag is set.
     */
    public String proxyHost() {
        return proxyHost;
    }

    /**
     * Proxy port.
     * 
     * @return The port to access the proxy on.  Only use this if the
     * useProxy flag is set
     */
    public int proxyPort() {
        return proxyPort;
    }

    /**
     * Sets proxy information
     * 
     * @param host The name of the proxy
     * @param port The port to access the proxy on
     */
    public void setProxy(String host, int port) {
        proxyHost = host;
        proxyPort = port;
        updateProxyInfo();
    }

    /**
     * Sets the genome download location.
     * 
     * @param url The URL under which new genomes can be downloaded
     */
    public void setGenomeDownloadLocation(String url) {
        genomeDownloadLocation = url;
    }

    /**
     * Custom genome base used.
     * 
     * @return true, a non-default genome folder has been selected
     */
    public boolean customGenomeBaseUsed() {
        /**
         * Says whether the user has specified a genome base location
         * of if we're using the default one.
         */

        // genomeBase will be null if we're using the default

        return genomeBase != null;
    }

    /**
     * Gets the genome base.
     * 
     * @return The folder under which genomes are stored
     * @throws FileNotFoundException 
     */
    public File getGenomeBase() throws FileNotFoundException {

        /*
         * This method returns a file which represents the directory
         * under which the genomes are stored.  If a custom location
         * has not been specified then the default Genomes folder in
         * the install dir is returned.  If that can't be found then
         * a FileNotFound exception is thrown
         * 
         * If a custom location has been set then this is returned
         * regardless of it it exists or can be used.
         */

        File f;

        if (genomeBase == null) {
            // Check for the default genomes folder.  This should always be present, but
            // you can't be too careful!
            try {
                f = new File(ClassLoader.getSystemResource("Genomes").getFile().replaceAll("%20", " "));
            } catch (NullPointerException npe) {
                throw new FileNotFoundException("Couldn't find default Genomes folder");
            }
        } else {
            f = genomeBase;
        }

        return f;
    }

    /**
     * Gets the genome download location.
     * 
     * @return The URL under which new genomes can be downloaded
     */
    public String getGenomeDownloadLocation() {
        return genomeDownloadLocation;
    }

    /**
     * Sets the genome base location
     * 
     * @param f The folder under which new genomes should be stored
     */
    public void setGenomeBase(File f) {
        // If this file is the same as the default then
        // we leave the default in place
        try {
            if (!f.equals(getGenomeBase())) {
                genomeBase = f;
            }
        } catch (FileNotFoundException e) {
            genomeBase = f;
        }
    }

    /**
     * Gets the default save location for projects / images / reports etc.
     * This will initially be the location in the preferences file but will
     * be updated during use to reflect the last actually used location.
     * 
     * @return The default save location.
     */
    public File getSaveLocation() {
        if (lastUsedSaveLocation != null)
            return lastUsedSaveLocation;
        return saveLocation;
    }

    /**
     * Gets the default save location from the preferences file.  This value
     * will always match the preferences file and will not update to reflect
     * actual usage within the current session.
     * 
     * @return The default save location
     */
    public File getSaveLocationPreference() {
        /**
         * Always returns the save location saved in the preferences file.  Used by
         * the preferences editing dialog.  Everywhere else should use getSaveLocation()
         */
        return saveLocation;
    }

    /**
     * Sets the save location to record in the preferences file
     * 
     * @param f The new save location
     */
    public void setSaveLocation(File f) {
        saveLocation = f;
    }

    /**
     * Sets the last used save location.  This is a temporary setting and will
     * not be recorded in the preferences file.
     * 
     * @param f The new last used save location
     */
    public void setLastUsedSaveLocation(File f) {
        if (f.isDirectory()) {
            lastUsedSaveLocation = f;
        } else {
            lastUsedSaveLocation = f.getParentFile();
        }
    }

    /**
     * Sets the list of ignored feature types
     * 
     * @param s The new list of ignored feature types
     */
    public void setIgnoredFeatures(String[] s) {
        ignoredAnnotations = new HashSet<String>(s.length);
        for (int i = 0; i < s.length; i++) {
            ignoredAnnotations.add(s[i]);
        }
    }

    /**
     * Applies the stored proxy information to the environment of the
     * current session so it is picked up automatically by any network
     * calls made within the program.  No further configuration is 
     * required within classes requiring network access.
     */
    private void updateProxyInfo() {
        if (useProxy) {
            System.getProperties().put("proxySet", "true");
            System.getProperties().put("proxyHost", proxyHost);
            System.getProperties().put("proxyPort", "" + proxyPort);
        } else {
            System.getProperties().put("proxySet", "false");
        }
    }
}