    001// Copyright 2007 by Basil Vandegriend.  All rights reserved.
    002
    003package com.basilv.envgen;
    004
    005import com.basilv.core.Assert;
    006import com.basilv.core.StringUtilities;
    007import 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 */
    022public 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                                        String propertyName = reader.get(0);
    042                                        if (isComment(propertyName)) {
    043                                                continue;
    044                                        }
    045
    046                                        int columnCount = reader.getColumnCount();
    047                                        Assert.isTrue("Must have at least two columns - one for the property name " +
    048                                                "and one row per environment for the property value.", columnCount > 1);
    049                                        if (rowNumber == FIRST_ROW) {
    050                                                int envCount = columnCount - 1;
    051                                                envProps = new EnvironmentProperties(envCount);
    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}