Configuration.java

package edu.hawaii.ics.yucheng;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Properties;

/**
 * An immutable class that contains the configuration information for a cluster
 * of nodes and a catalog. They are parsed from the 'clustercfg' file.
 * 
 * @author     Cheng Jade
 * @assignment ICS 421 Assignment 2-2
 * @date       Feb 29, 2010
 * @bugs       None
 */
public final class Configuration {

    // The catalog node configuration
    private final ConfigurationNode catalog;

    // The table name
    private final String tableName;

    // The partition method
    private final String partitionMethod;

    // The partition column
    private final String partionColumn;

    // The partition number
    private final int partionNumber;

    // The array of nodes configurations.
    private final ArrayList<ParameterPair> partitionList = new ArrayList<ParameterPair>();
    
    // The array of nodes configurations.
    private final ArrayList<ConfigurationNode> nodeList = new ArrayList<ConfigurationNode>();
    
    // method to add a node in a configuration list.
    public boolean addNode(ConfigurationNode node){
        assert null != node;
        for (int i = 0; i < nodeList.size(); i++)
            if (nodeList.get(i).equals(node))
                    return false;
        nodeList.add(node);
        return true;
    }

    /**
     * Initializes a new instance of the Configuration class.
     * 
     * @param path
     *            The path to a file that contains configuration data.
     * 
     * @throws NullPointerException
     * @throws ProgramException
     *             Thrown if it cann't read the DDL command file, or the
     *             specified path is null.
     */
    public Configuration(final String path) throws ProgramException {

        // Throw an exception if the specified path is null.
        if (null == path)
            throw new NullPointerException("path");

        // Declare a Properties object and load it with the specified file.
        final Properties properties = getProperties(path);

        // Obtain the catalog configuration.
        this.catalog = new ConfigurationNode(properties, "catalog");
        
        // Obtain the table name.
        this.tableName = properties.getProperty("tablename");
        
        // Obtain the partition method.
        this.partitionMethod = properties.getProperty("partition.method");
        
        // Obtain the partition column.
        this.partionColumn = properties.getProperty("partition.column");        

        String partionNumberText = null;
        if (this.partitionMethod.equalsIgnoreCase("hash"))
            partionNumberText= properties.getProperty("partition.param1");
        else
            if (this.partitionMethod.equalsIgnoreCase("range"))
                partionNumberText= properties.getProperty("numnodes");
            else
                throw new ProgramException("invalid partition method.");

        if (null == partionNumberText)
            throw new ProgramException(
                    "can't find partition number field in the configuration file.");

        try {
            partionNumber = Integer.parseInt(partionNumberText);
        } catch (final NumberFormatException e) {
            throw new ProgramException("Cannot parse number of partitions.", e);
        }
        
        if (this.partitionMethod.equalsIgnoreCase("hash")) {
            for (int i = 0; i < this.partionNumber; i++)
                partitionList.add(new ParameterPair(properties.getProperty("partition.param1")));
            return;
        }

        for (int i = 0; i < this.partionNumber; i++)
            partitionList.add(new ParameterPair(properties, i + 1));
    }

    /**
     * Returns the catalog configuration.
     * 
     * @return The catalog configuration.
     */
    public ConfigurationNode getCatalog() {
        return this.catalog;
    }
    
    // added when doing A2
    public ConfigurationNode getNode(int index) {
        return this.nodeList.get(index);
    }    
    
    // added when doing A2
    public ParameterPair getPartition(int index) {
        return this.partitionList.get(index);
    }
    
    // added when doing A2
    public String getTableName() {
        return this.tableName;
    }
    
    // added when doing A2
    public String getPartitionMethod() {
        return this.partitionMethod;
    }
    
    // added when doing A2
    public String getPartitionColumn() {
        return this.partionColumn;
    }
    
    // added when doing A2
    public int nodeListsize() {
        return this.nodeList.size();
    }
    
    // added when doing A2
    public int partitionListsize() {
        return this.partitionList.size();
    }

    /**
     * Returns a readable version of the contents of the configuration.
     * 
     * @return A readable version of the contents of the configuration.
     */
    @Override
    public String toString() {

        // If the directory is empty, return a special note.
        if (this.partitionList.size() == 0)
            return "The partition list is empty.\n";

        // Loop over each item, and add it to the string builder.
        final StringBuilder builder = new StringBuilder();
        builder.append("The configuration file contains:\n\n");
        builder.append("Catalog: \n");
        builder.append(this.catalog + "\n\n");
        builder.append("Table Name: ");
        builder.append(this.tableName + "\n");
        builder.append("Partition Method: ");
        builder.append(this.partitionMethod + "\n");
        builder.append("Partition Column: ");
        builder.append(this.partionColumn + "\n");
        builder.append("Partition Number: ");
        builder.append(this.partionNumber);
        
        for (int i = 0; i < this.partionNumber; i++) {
            builder.append("\n\nPartition ");
            builder.append(i + 1);
            builder.append(": \n");
            builder.append(partitionList.get(i));
        }
        
        if (nodeList.size() == 0)
            builder.append("\n\nConfiguration node list is empty.");
        else
            for (int i = 0; i < this.nodeList.size(); i++) {
                builder.append("\n\nNode ");
                builder.append(i + 1);
                builder.append(": \n");
                builder.append(nodeList.get(i));
            }
        

        // Return the string created above.
        return builder.toString();
    }

    /**
     * Open a file, check for errors, and return a loaded properties object.
     * 
     * @param path
     *            The path to the properties file.
     * 
     * @return A loaded properties object.
     * 
     * @throws ProgramException
     *             Thrown if there is a problem reading the configuration file.
     */
    private static Properties getProperties(final String path)
            throws ProgramException {
        assert null != path;

        try {
            final FileInputStream file = new FileInputStream(path);
            try {
                final Properties properties = new Properties();
                properties.load(file);
                return properties;
            } finally {
                file.close();
            }
        } catch (final IOException e) {
            throw new ProgramException("Cannot read configuration file.", e);
        }
    }

    /**
     * The test main, the entry point when testing this class.
     * 
     * @param args
     *            The command line arguments.
     */
    public static void main(final String[] args) {
        assert null != args;

        // Print usage information, if wrong number of arguments were used.
        if (args.length != 1) {
            final String name = Configuration.class.getSimpleName();
            System.err.println("Usage: java " + name + " <path>");
            System.err.println("       <path> path to a configuration file");
            System.exit(1);
            return;
        }

        // Declare a Configuration object and populate it with data from a file
        // that is specified as the only command line argument.
        try {
            assert null != args[0];
            System.out.println(new Configuration(args[0]));

        } catch (final ProgramException e) {
            System.err.println(e.getMessage());
            System.exit(1);
            return;
        }

        // Exit cleanly while debugging from Eclipse.
        System.exit(0);
    }
}
Valid HTML 4.01 Valid CSS