/*
 * Created on Mar 10, 2005 <p>
 * By Eddie <p>
 * Usage of this class requires that biomoby.properties is configured correctly
 * and that a config property pointing to the file mobycentral.config is valid. 
 */
package org.biomoby.registry.properties;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.biomoby.shared.MobyException;

/**
 * @author Eddie Kawas
 * <p>This class was created to provide a way of querying a users local registry and 
 * obtaining information of objects in the BioMoby Ontologies.. If you do not
 * have a local registry, this class will not function correctly.
 * <p>For questions, comments, or bugs
 * <p>email me at edward.kawas@gmail.com
 */
@SuppressWarnings("unchecked")
public class MobyCentralConfig {

    private static Log log = LogFactory.getLog(MobyCentralConfig.class);
    
    private final static String location = getLocation();

    private final static String regexp = "^(\\w+)\\s*=\\s*(.*)$";
   
    /**
     * A method that retrieves the mySQL connection details for the database mobycentral. 
     * <p><b>PRE:</b> The property config is specified and configured correctly in the file biomoby.properties.
     * <p><b>POST:</b> Map consists of the mySQL connection information for the database mobycentral or MobyException is thrown.
     * @return - A Map of the mySQL connection information is returned. The Keys for the 
     * map are typically username, password, url, port, and dbname.
     * @throws MobyException - if biomoby.properties file cannot be found or is incorrectly configured.
     */
    public final static Map getMobyCentral() throws MobyException {
        Map map = new HashMap();
        getProperties("mobycentral", map);
        return map;
    }

    private static String getLocation() {
    	if (System.getProperty("MOBY_CENTRAL_CONFIG")==null) {
    		log.debug("getting MOBY_CENTRAL_CONFIG using MobyProperties()");
    		return MobyProperties.PROPERTIES().getProperty("MOBY_CENTRAL_CONFIG");
    	}
    	else {
    		// use the environment variables you set with your own registry
    		log.debug("getting MOBY_CENTRAL_CONFIG using System.getProperty()");
    		return System.getProperty("MOBY_CENTRAL_CONFIG"); 
    	}
	}

	/**
     * A method that retrieves the mySQL connection details for the database mobynamespace. 
     * <p><b>PRE:</b> The property config is specified and configured correctly in the file biomoby.properties.
     * <p><b>POST:</b> Map consists of the mySQL connection information for the database mobynamespace or MobyException is thrown.
     * @return - A Map of the mySQL connection information is returned. The Keys for the 
     * map are typically username, password, url, port, and dbname.
     * @throws MobyException - if biomoby.properties file cannot be found or is incorrectly configured.
     */    
    public final static Map getMobyNamespace() throws MobyException {
        Map map = new HashMap();
        getProperties("mobynamespace", map);
        return map;
    }

    /**
     * A method that retrieves the mySQL connection details for the database mobyobject. 
     * <p><b>PRE:</b> The property config is specified and configured correctly in the file biomoby.properties.
     * <p><b>POST:</b> Map consists of the mySQL connection information for the database mobyobject or MobyException is thrown.
     * @return - A Map of the mySQL connection information is returned. The Keys for the 
     * map are typically username, password, url, port, and dbname.
     * @throws MobyException - if biomoby.properties file cannot be found or is incorrectly configured.
     */
    public final static Map getMobyObject() throws MobyException {
        Map map = new HashMap();
        getProperties("mobyobject", map);
        return map;
    }

    /**
     * A method that retrieves the mySQL connection details for the database mobyservice. 
     * <p><b>PRE:</b> The property config is specified and configured correctly in the file biomoby.properties.
     * <p><b>POST:</b> Map consists of the mySQL connection information for the database mobyservice or MobyException is thrown.
     * @return - A Map of the mySQL connection information is returned. The Keys for the 
     * map are typically username, password, url, port, and dbname.
     * @throws MobyException - if biomoby.properties file cannot be found or is incorrectly configured.
     */
    public final static Map getMobyService() throws MobyException {
        Map map = new HashMap();
        getProperties("mobyservice", map);
        return map;
    }

    /**
     * A method that retrieves the mySQL connection details for the database mobyrelationship. 
     * <p><b>PRE:</b> The property config is specified and configured correctly in the file biomoby.properties.
     * <p><b>POST:</b> Map consists of the mySQL connection information for the database mobyrelationship or MobyException is thrown.
     * @return - A Map of the mySQL connection information is returned. The Keys for the 
     * map are typically username, password, url, port, and dbname.
     * @throws MobyException - if biomoby.properties file cannot be found or is incorrectly configured.
     */
    public final static Map getMobyRelationship() throws MobyException {
        Map map = new HashMap();
        getProperties("mobyrelationship", map);
        return map;
    }

    private final static void getProperties(String name, Map map)
            throws MobyException {
    	if (location == null)
    		throw new MobyException(
                    "Error - MOBY_CENTRAL_CONFIG ==  null;"
                            + " Make sure that MOBY_CENTRAL_CONFIG is set correctly in the environment");
        File file = new File(location);
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(file));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            throw new MobyException(
                    "Could not read from "
                            + location
                            + ". Please make sure your file pointed to by env{MOBY_CENTRAL_CONFIG} is complete and valid.");
        }
        String line = "";
        try {
            while ((line = br.readLine()) != null) {
                if (line.equalsIgnoreCase("[" + name + "]")) {
                    while ((line = br.readLine()) != null) {
                        // exit condition
                        if (line.indexOf("[") >= 0 && line.indexOf("]") > 0) {
                            return;
                        }
                        if (Pattern.compile(regexp).matcher(line).matches()) {
                            String key = parse(line, 1);
                            String value = parse(line, 2);
                            map.put(key, value);
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new MobyException(
                    "Error reading file "
                            + location
                            + ". Make sure that no other process was modifying this file.");
        }
    }

    private static String parse(String string, int groupid)
            throws MobyException {
        Pattern p = Pattern.compile(regexp);
        Matcher m = p.matcher(string);
        if (m.matches())
            return m.group(groupid);
        else
            throw new MobyException("configuration file isn't as expected");

    }

    /**
     * 
     * a brief test application that outputs the information obtained by calling
     * each of the methods in this class. If biomoby.properties is incorrectly configured
     * then MobyException is thrown.
     */
    public static void main(String[] args) throws MobyException {
        System.out.println(MobyCentralConfig.getMobyNamespace());
        System.out.println(MobyCentralConfig.getMobyObject());
        System.out.println(MobyCentralConfig.getMobyService());
        System.out.println(MobyCentralConfig.getMobyRelationship());
        System.out.println(MobyCentralConfig.getMobyCentral());
    }

}
