/*
 * $Source: /usr/local/cvsroot/erserver/erserver/java/src/com/postgres/util/config/ReplicationConfig.java,v $
 * $Author: asullivan $ $Revision: 1.1.1.1 $ $Date: 2003/08/26 19:02:33 $
 *
 */

package com.postgres.util.config;

import java.util.*;
import com.postgres.util.Logger.*;

public class ReplicationConfig implements ConfiguratorIntf {
    protected ReplicationConfig() { }

    public static ReplicationConfig getInstance() {
        if (instance == null) {
            instance = new ReplicationConfig();
        }
        return instance;
    }

    /**
     * @link
     * @shapeType PatternLink
     * @pattern <{com.postgres.util.config.ReplicationConfig}>
     * @supplierRole Singleton factory
     */

    /*# private ReplicationConfig _singleton; */

    private static ReplicationConfig instance = null;

    private static final String CONFIG_FILE_NAME = "replication.cfg";
    private Properties props;
    private boolean initialized;
    private boolean debug;

    public boolean getDebug() {
        return debug;
    }

    public void setDebug(boolean debug){
        this.debug = debug;
    }

    /**
     * <p>Initializes the ConnectionPool object using
     * 'ConnectionPool.cfg' as the configuration file
     * @return true if the ConnectionPool was initialized properly
     */
    public void initialize() throws Exception {
        initialize(CONFIG_FILE_NAME);
    }

    /**
     * <p>Initializes the ConnectionPool object with the specified
     * configuration file
     * @param config Configuration file name
     * @return true if the ConnectionPool was initialized properly
     */
    public void initialize(String config) throws Exception {
        // Load the configuration parameters.
        loadConfig(config);
        initialized = true;
    }

    public boolean initialized() {
        return initialized;
    }

    /**
     * <p>Loads the given configuration file.  All global properties will be
     * read and removed from the properties list. Any leftover
     * properties will be returned. Returns null if the
     * properties could not be loaded
     * @param name Configuration file name
     * @return config Properties if the configuration file was loaded
     */
    private void loadConfig(String name)
    throws Exception {
        if (props != null) {
            return;
        }
        java.io.InputStream in = null;

        try {
            // Get our class loader
            ClassLoader cl = getClass().getClassLoader();

            // Attempt to open an input stream to the configuration file.
            // The configuration file is considered to be a system
            // resource.
            if (cl != null) {
                in = cl.getResourceAsStream(name);
            } else {
                in = ClassLoader.getSystemResourceAsStream(name);
            }
            props = new java.util.Properties();

            // Load the configuration file into the properties table
            props.load(in);


            // If the input stream is null, then the configuration file
            // was not found
            if (in == null) {
                throw new Exception("Configuration file '" +
                name + "' not found");
            } else {

            }
        } catch (Exception e) {
            throw new Exception("ReplicationConfig::loadConfig: "
            + e.toString());
        } finally {
            // Always close the input stream
            if (in != null) {
                try {
                    in.close();
                } catch (Exception ex) { }
            }


        } // try
    }

    private void validateInitialized(String errorPrefix) throws Exception {
        if (!initialized) {
            throw new Exception("ReplicationConfig::"
            + errorPrefix + "Properties heave not been set");
        }
    }

    /**
     * <p>Retrieves the given property and returns the value.
     * @param properties Properties table
     * @param key Key of the property to retrieve and remove from
     * @param key Key of the property to retrieve and remove from
     * the properties table
     * @return Value of the property, or null if not found
     */
    public String getProperty(String key, String defaultKey)
    throws Exception {
        validateInitialized("getProperty: ") ;
        String s = null;

        if (key != null) {
            s = props.getProperty(key, defaultKey);
        }
        return s;
    }

    public String getProperty(String key)
    throws Exception {
        validateInitialized("getProperty: ");
        String s = null;

        if (key != null) {
            s = props.getProperty(key);
        }
        return s;
    }

    public int getPropertyInt(String key, int defaultKey)
    throws Exception {
        String s = getProperty(key,
            new Integer(defaultKey).toString());
        return Integer.parseInt(s);
    }

    public int getPropertyInt(String key)
    throws Exception {
        String s = getProperty(key);
        return Integer.parseInt(s);
    }

    public ArrayList getListProperty(String name) throws Exception {
        if(getDebug()) getLogger().debug("ReplicationConfig::getListProperty: BEGIN");
        ArrayList list = new ArrayList();
        StringTokenizer tok = new StringTokenizer(getProperty(name), ",");
        while (tok.hasMoreElements()) {
            list.add(tok.nextToken().trim());
        }
        return list;
    }

    public ArrayList getListProperty(String name, ArrayList defaultList)
    throws Exception {

        String value = getProperty(name);
        ArrayList list = null;
        if (value != null) {
            list = new ArrayList();
            StringTokenizer tok = new StringTokenizer(value, ",");
            while (tok.hasMoreElements()) {
                list.add(tok.nextToken().trim());
            }
        }

        // if list is null or list size < default list size -
        if (defaultList != null) {
            if ((list == null || list.size() < defaultList.size()) ) {
                int begin = (list == null) ? 0 : list.size();
                for (int i=begin; i<defaultList.size(); i++) {
                	list.add(defaultList.get(i));
                }
            }
        }

        /*
        if (defaultList != null && defaultList.size() > 0 && list != null && list.size() > 0) {
             if (list.size() != defaultList.size()) {
                throw new Exception("ReplicationConig::getListProperty: list.size() != defaultList.size()");
             }
             for (int i=0; i<defaultList.size(); i++) {
                 String prop = list.get(i) == null ? (String) defaultList.get(i) : (String) list.get(i);
                 list.add(prop);
             }
        }
        */

        return list;
    }

    public void printProps(String header) {
        if (header == null) {
            header = "-- ReplicationConfig -- ";
        }
        if (props == null) {
            getLogger().info(header + " : ReplicationConfig::printProps: properties are not set!");
            return;
        }

        getLogger().info(header);
        if (props != null) {
            Iterator iterator = props.keySet().iterator();
            while (iterator.hasNext()) {
               String key = (String) iterator.next();
               String value = (String) props.get(key);
               getLogger().info("        key="+key + "; value=" + value);
            }
        }
    }

    protected Logger getLogger() {
         return LogRepl.getInstance();
    }

}
