org.linqs.psl.config.Config.java Source code

Java tutorial

Introduction

Here is the source code for org.linqs.psl.config.Config.java

Source

/*
 * This file is part of the PSL software.
 * Copyright 2011-2015 University of Maryland
 * Copyright 2013-2018 The Regents of the University of California
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.linqs.psl.config;

import org.linqs.psl.util.Reflection;

import org.apache.commons.configuration2.BaseConfiguration;
import org.apache.commons.configuration2.DataConfiguration;
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.log4j.helpers.Loader;
import org.apache.log4j.helpers.OptionConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * The storage for all configuration values used in PSL.
 * No prefixes are used (unlike previous config infrastructure).
 * All access to configuration is static.
 *
 * Properties can be managed through the following methods:
 * loadResource(), addProperty(), setProperty(), clearProperty(), clear().
 *
 * PSL will statically try to load a properties file pointed to by the "psl.configuration"
 * system property ("psl.properties" by default.
 */
public class Config {
    public static final String PROJECT_PROPS = "project.properties";
    public static final String PSL_CONFIG = "psl.configuration";
    public static final String PSL_CONFIG_DEFAULT = "psl.properties";

    private static final Logger log = LoggerFactory.getLogger(Config.class);

    private static DataConfiguration config = null;

    static {
        init();
    }

    /**
     * (Re)create and populate the initial config.
     */
    public static void init() {
        config = new DataConfiguration(new BaseConfiguration());

        // Load maven project properties.
        InputStream stream = ClassLoader.getSystemClassLoader().getResourceAsStream(PROJECT_PROPS);
        if (stream != null) {
            loadResource(stream, PROJECT_PROPS);
        }

        // Load the configuration file directly if the path exists.
        String path = OptionConverter.getSystemProperty(PSL_CONFIG, PSL_CONFIG_DEFAULT);
        if ((new File(path)).isFile()) {
            loadResource(path);
            return;
        }

        // Try to get a resource URL from the system (if we have a property key instead of a path).
        stream = ClassLoader.getSystemClassLoader().getResourceAsStream(path);
        if (stream != null) {
            loadResource(stream, PSL_CONFIG);
            return;
        }

        log.debug("PSL configuration {} file not found."
                + " Only default values will be used unless additional properties are specified.", path);
    }

    public static void loadResource(InputStream stream, String resourceName) {
        try {
            PropertiesConfiguration props = new PropertiesConfiguration();
            props.read(new InputStreamReader(stream));
            config.append(props);
        } catch (IOException | ConfigurationException ex) {
            throw new RuntimeException("Failed to load config resource: " + resourceName, ex);
        }

        log.debug("Configuration stream loaded: {}", resourceName);
    }

    public static void loadResource(String path) {
        try {
            PropertiesConfiguration props = new PropertiesConfiguration();
            props.read(new FileReader(path));
            config.append(props);
        } catch (IOException | ConfigurationException ex) {
            throw new RuntimeException("Failed to load config resource: " + path, ex);
        }

        log.debug("Configuration file loaded: {}", path);
    }

    /**
     * Add a property to the configuration.
     * If it already exists then the value stated here will be added to the configuration entry.
     * For example, if the property:
     *
     * <pre>
     * resource.loader = file
     * </pre>
     *
     * is already present in the configuration and you call
     *
     * <pre>
     * addProperty(&quot;resource.loader&quot;, &quot;classpath&quot;)
     * </pre>
     *
     * Then you will end up with a List like the following:
     *
     * <pre>
     * ["file", "classpath"]
     * </pre>
     *
     * @param key The key to add the property to.
     * @param value The value to add.
     */
    public static void addProperty(String key, Object value) {
        config.addProperty(key, value);
        log.debug("Added {} to option {}.", value, key);
    }

    /**
     * Set a property, this will replace any previously set values.
     * Set values is implicitly a call to clearProperty(key), addProperty(key, value).
     *
     * @param key the key to remove along with corresponding value.
     */
    public static void setProperty(String key, Object value) {
        config.setProperty(key, value);
        log.debug("Set option {} to {}.", key, value);
    }

    /**
     * Remove a property from the configuration.
     *
     * @param key the key to remove along with corresponding value.
     */
    public static void clearProperty(String key) {
        config.clearProperty(key);
        log.debug("Cleared option {}.", key);
    }

    /**
     * Remove all properties from the configuration.
     */
    public static void clear() {
        config.clear();
        log.debug("Cleared all options in the configuration.");
    }

    /**
     * Get a property from the configuration.
     * Typically, a more specific method should be used.
     *
     * @param key The configuration key
     *
     * @return The associated Object (or null if undefined)
     */
    public static Object getProperty(String key) {
        logAccess(key, "");
        if (config.containsKey(key)) {
            return config.getProperty(key);
        }

        return null;
    }

    public static boolean getBoolean(String key, boolean defaultValue) {
        logAccess(key, defaultValue);
        return config.getBoolean(key, defaultValue);
    }

    public static Boolean getBoolean(String key, Boolean defaultValue) {
        logAccess(key, defaultValue);
        return config.getBoolean(key, defaultValue);
    }

    public static Double getDouble(String key, Double defaultValue) {
        logAccess(key, defaultValue);
        return config.getDouble(key, defaultValue);
    }

    public static String getString(String key, String defaultValue) {
        logAccess(key, defaultValue);
        return config.getString(key, defaultValue);
    }

    public static byte getByte(String key, byte defaultValue) {
        logAccess(key, defaultValue);
        return config.getByte(key, defaultValue);
    }

    public static Byte getByte(String key, Byte defaultValue) {
        logAccess(key, defaultValue);
        return config.getByte(key, defaultValue);
    }

    public static double getDouble(String key, double defaultValue) {
        logAccess(key, defaultValue);
        return config.getDouble(key, defaultValue);
    }

    public static float getFloat(String key, float defaultValue) {
        logAccess(key, defaultValue);
        return config.getFloat(key, defaultValue);
    }

    public static Float getFloat(String key, Float defaultValue) {
        logAccess(key, defaultValue);
        return config.getFloat(key, defaultValue);
    }

    public static int getInt(String key, int defaultValue) {
        logAccess(key, defaultValue);
        return config.getInt(key, defaultValue);
    }

    public static Integer getInteger(String key, Integer defaultValue) {
        logAccess(key, defaultValue);
        return config.getInteger(key, defaultValue);
    }

    public static long getLong(String key, long defaultValue) {
        logAccess(key, defaultValue);
        return config.getLong(key, defaultValue);
    }

    public static Long getLong(String key, Long defaultValue) {
        logAccess(key, defaultValue);
        return config.getLong(key, defaultValue);
    }

    public static short getShort(String key, short defaultValue) {
        logAccess(key, defaultValue);
        return config.getShort(key, defaultValue);
    }

    public static Short getShort(String key, Short defaultValue) {
        logAccess(key, defaultValue);
        return config.getShort(key, defaultValue);
    }

    public static BigDecimal getBigDecimal(String key, BigDecimal defaultValue) {
        logAccess(key, defaultValue);
        return config.getBigDecimal(key, defaultValue);
    }

    public static BigInteger getBigInteger(String key, BigInteger defaultValue) {
        logAccess(key, defaultValue);
        return config.getBigInteger(key, defaultValue);
    }

    public static List<String> getList(String key, List<String> defaultValue) {
        logAccess(key, defaultValue);
        List<?> configList = config.getList(key, defaultValue);

        List<String> toReturn = new ArrayList<String>(configList.size());
        for (Object item : configList) {
            toReturn.add((String) item);
        }

        return toReturn;
    }

    /**
     * Returns a new instance of the class whose name associated with the given configuration key.
     * The default constructor will be used.
     */
    public static Object getNewObject(String key, String defaultValue) {
        logAccess(key, defaultValue);

        String className = config.getString(key, defaultValue);

        // It is not unusual for someone to want no object if the key does not exist.
        if (className == null) {
            return null;
        }

        return Reflection.newObject(className);
    }

    public static String asString() {
        StringBuilder string = new StringBuilder();

        @SuppressWarnings("unchecked")
        Iterator<String> keys = config.getKeys();
        while (keys.hasNext()) {
            String key = keys.next();
            string.append(key + ": " + config.getProperty(key) + "\n");
        }

        return string.toString();
    }

    private static void logAccess(String key, Object defaultValue) {
        if (config.containsKey(key)) {
            log.debug("Found value {} for option {}.", config.getProperty(key), key);
        } else {
            log.debug("No value found for option {}. Returning default of {}.", key, defaultValue);
        }
    }
}