    001    // Copyright 2007 by Basil Vandegriend.  All rights reserved.
    002
    003    package com.basilv.envgen;
    004
    005    import com.basilv.core.Assert;
    006    import com.basilv.core.StringUtilities;
    007    import com.csvreader.CsvReader;
    008
    009    /**
    010     * Loads environment properties from the specified CSV file and populates an instance of
    011     * EnvironmentProperties.
    012     *
    013     * The file format is as follows:
    014     * <ul>
    015     * <li>Each row corresponds to a single property or to a comment.</li>
    016     * <li>For a property, the first column contains the name of the property.<br>
    017     * Each subsequent column contains the value of the property for a single environment.</li>
    018     * <li>For a comment, the first column must start with the symbol '#' or '//', or be completely empty.
    019     * The remainder of the row is ignored. </li>
    020     * </ul>
    021     */
    022    public class EnvironmentPropertiesLoader
    023    {
    024
    025            /**
    026             * Load the CSV file into an EnvironmentProperties instance.
    027             * @param filename  Cannot be null or empty. Must correspond to a CSV file of the correct format.
    028             * @return the EnvironmentProperties instance.
    029             */
    030            public static EnvironmentProperties load(String filename) {
    031                    Assert.notNullOrEmpty("filename", filename);
    032
    033                    try {
    034                            CsvReader reader = new CsvReader(filename);
    035                            try {
    036                                    EnvironmentProperties envProps = null;
    037
    038                                    final int FIRST_ROW = 1;
    039                                    int rowNumber = FIRST_ROW; // Indexed from one.
    040                                    while (reader.readRecord()) {
    041                                            int columnCount = reader.getColumnCount();
    042                                            Assert.isTrue("Must have at least two columns - one for the property name " +
    043                                                    "and one row per environment for the property value.", columnCount > 1);
    044                                            if (rowNumber == FIRST_ROW) {
    045                                                    int envCount = columnCount - 1;
    046                                                    envProps = new EnvironmentProperties(envCount);
    047                                            }
    048
    049                                            String propertyName = reader.get(0);
    050                                            if (isComment(propertyName)) {
    051                                                    continue;
    052                                            }
    053
    054                                            for (int column = 1; column < columnCount; column++) {
    055                                                    int environment = column - 1;
    056                                                    String propertyValue = reader.get(column);
    057                                                    envProps.addProperty(environment, propertyName, propertyValue);
    058                                            }
    059
    060                                            rowNumber++;
    061                                    }
    062                                    if (envProps == null) {
    063                                            Assert.shouldNotReach("File [" + filename + "] does not contain any rows.");
    064                                    }
    065
    066                                    return envProps;
    067
    068                            } finally {
    069                                    reader.close();
    070                            }
    071                    } catch (Exception e) {
    072                            throw new RuntimeException("Error reading cvs file [" +
    073                                    filename + "] due to " + e.getMessage() + ".", e);
    074                    }
    075
    076            }
    077
    078            // Non-private for testing
    079            static boolean isComment(String propertyName) {
    080                    if (StringUtilities.isNullOrEmpty(propertyName)) {
    081                            return true;
    082                    }
    083
    084                    if (propertyName.startsWith("#")) {
    085                            return true;
    086                    }
    087
    088                    if (propertyName.startsWith("//")) {
    089                            return true;
    090                    }
    091
    092                    return false;
    093            }
    094
    095    }