187 lines
7.1 KiB
Java
187 lines
7.1 KiB
Java
package envoy.data;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.util.*;
|
|
import java.util.function.Function;
|
|
import java.util.logging.Level;
|
|
import java.util.stream.Collectors;
|
|
|
|
import envoy.util.EnvoyLog;
|
|
|
|
/**
|
|
* Manages all application settings that are set during application startup by
|
|
* either loading them from the {@link Properties} file
|
|
* {@code client.properties} or parsing them from the command line arguments of
|
|
* the application.<br>
|
|
* <br>
|
|
* Project: <strong>envoy-client</strong><br>
|
|
* File: <strong>Config.java</strong><br>
|
|
* Created: <strong>12 Oct 2019</strong><br>
|
|
*
|
|
* @author Kai S. K. Engelbart
|
|
* @since Envoy Common v0.1-beta
|
|
*/
|
|
public class Config {
|
|
|
|
protected Map<String, ConfigItem<?>> items = new HashMap<>();
|
|
|
|
private boolean modificationDisabled;
|
|
|
|
protected Config(String folderName) {
|
|
final var rootDirectory = new File(System.getProperty("user.home"), folderName);
|
|
put("homeDirectory", "home", File::new, true);
|
|
((ConfigItem<File>) get("homeDirectory")).setValue(rootDirectory);
|
|
put("fileLevelBarrier", "fb", Level::parse, true);
|
|
put("consoleLevelBarrier", "cb", Level::parse, true);
|
|
}
|
|
|
|
/**
|
|
* Parses config items from a properties object.
|
|
*
|
|
* @param properties the properties object to parse
|
|
* @since Envoy Common v0.1-beta
|
|
*/
|
|
private void load(Properties properties) {
|
|
items.entrySet()
|
|
.stream()
|
|
.filter(e -> properties.containsKey(e.getKey()))
|
|
.forEach(e -> e.getValue().parse(properties.getProperty(e.getKey())));
|
|
}
|
|
|
|
/**
|
|
* Parses config items from an array of command line arguments.
|
|
*
|
|
* @param args the command line arguments to parse
|
|
* @throws IllegalStateException if a malformed command line argument has been
|
|
* supplied
|
|
* @since Envoy Common v0.1-beta
|
|
*/
|
|
private void load(String[] args) {
|
|
for (int i = 0; i < args.length; i++)
|
|
for (final ConfigItem<?> item : items.values())
|
|
if (args[i].startsWith("--")) {
|
|
if (args[i].length() == 2) throw new IllegalStateException("Malformed command line argument at position " + i + ": " + args[i]);
|
|
final String commandLong = args[i].substring(2);
|
|
if (item.getCommandLong().equals(commandLong)) {
|
|
item.parse(args[++i]);
|
|
break;
|
|
}
|
|
} else if (args[i].startsWith("-")) {
|
|
if (args[i].length() == 1) throw new IllegalStateException("Malformed command line argument at position " + i + ": " + args[i]);
|
|
final String commandShort = args[i].substring(1);
|
|
if (item.getCommandShort().equals(commandShort)) {
|
|
item.parse(args[++i]);
|
|
break;
|
|
}
|
|
} else throw new IllegalStateException("Malformed command line argument at position " + i + ": " + args[i]);
|
|
}
|
|
|
|
/**
|
|
* Supplies default values from the given .properties file and
|
|
* parses the configuration from an array of command line arguments.
|
|
*
|
|
* @param declaringClass the class calling this method
|
|
* @param propertiesFilePath the path to where the .properties file can be found
|
|
* - will be only the file name if it is located
|
|
* directly inside the {@code src/main/resources}
|
|
* folder
|
|
* @param args the command line arguments to parse
|
|
* @throws IllegalStateException if this method is getting called again or if a
|
|
* malformed command line argument has been
|
|
* supplied
|
|
* @since Envoy Common v0.1-beta
|
|
*/
|
|
public void loadAll(Class<?> declaringClass, String propertiesFilePath, String[] args) {
|
|
if (modificationDisabled) throw new IllegalStateException("Cannot change config after isInitialized has been called");
|
|
// Load the defaults from the given .properties file first
|
|
final var properties = new Properties();
|
|
try {
|
|
properties.load(declaringClass.getClassLoader().getResourceAsStream(propertiesFilePath));
|
|
} catch (final IOException e) {
|
|
EnvoyLog.getLogger(Config.class).log(Level.SEVERE, "An error occurred when reading in the configuration: ", e);
|
|
}
|
|
load(properties);
|
|
|
|
// Override configuration values with command line arguments
|
|
if (args.length > 0) load(args);
|
|
|
|
// Check if all mandatory configuration values have been initialized
|
|
isInitialized();
|
|
// Disable further editing of the config
|
|
modificationDisabled = true;
|
|
}
|
|
|
|
/**
|
|
* @throws IllegalStateException if a mandatory {@link ConfigItem} has not been
|
|
* initialized
|
|
* @since Envoy Common v0.1-beta
|
|
*/
|
|
private void isInitialized() {
|
|
if (items.values().stream().filter(ConfigItem::isMandatory).map(ConfigItem::get).anyMatch(Objects::isNull))
|
|
throw new IllegalStateException("config item(s) has/ have not been initialized:" + items.values()
|
|
.stream()
|
|
.filter(configItem -> configItem.isMandatory() && configItem.get() == null)
|
|
.map(ConfigItem::getCommandLong)
|
|
.collect(Collectors.toSet()));
|
|
}
|
|
|
|
/**
|
|
* @param name the name of the config item to return
|
|
* @return the config item with the specified name
|
|
* @since Envoy Common v0.1-beta
|
|
*/
|
|
public ConfigItem<?> get(String name) { return items.get(name); }
|
|
|
|
/**
|
|
* Shorthand for <br>
|
|
* {@code items.put(commandName, new ConfigItem<>(commandName, commandShort, parseFunction, defaultValue, mandatory))}.
|
|
*
|
|
* @param <T> the type of the {@link ConfigItem}
|
|
* @param commandName the key for this config item as well as its long name
|
|
* @param commandShort the abbreviation of this config item
|
|
* @param parseFunction the {@code Function<String, T>} that parses the value
|
|
* from a string
|
|
* @param mandatory indicated that this config item must be initialized with
|
|
* a non-null value
|
|
* @since Envoy Common v0.2-beta
|
|
*/
|
|
protected <T> void put(String commandName, String commandShort, Function<String, T> parseFunction, boolean mandatory) {
|
|
items.put(commandName, new ConfigItem<>(commandName, commandShort, parseFunction, mandatory));
|
|
}
|
|
|
|
/**
|
|
* Shorthand for <br>
|
|
* {@code put(commandName, commandShort, parseFunction, false)}.
|
|
*
|
|
* @param <T> the type of the {@link ConfigItem}
|
|
* @param commandName the key for this config item as well as its long name
|
|
* @param commandShort the abbreviation of this config item
|
|
* @param parseFunction the {@code Function<String, T>} that parses the value
|
|
* from a string
|
|
* @since Envoy Common v0.2-beta
|
|
*/
|
|
protected <T> void put(String commandName, String commandShort, Function<String, T> parseFunction) {
|
|
put(commandName, commandShort, parseFunction, false);
|
|
}
|
|
|
|
/**
|
|
* @return the directory in which all local files are saves
|
|
* @since Envoy Client v0.2-beta
|
|
*/
|
|
public File getHomeDirectory() { return (File) items.get("homeDirectory").get(); }
|
|
|
|
/**
|
|
* @return the minimal {@link Level} to log inside the log file
|
|
* @since Envoy Client v0.2-beta
|
|
*/
|
|
public Level getFileLevelBarrier() { return (Level) items.get("fileLevelBarrier").get(); }
|
|
|
|
/**
|
|
* @return the minimal {@link Level} to log inside the console
|
|
* @since Envoy Client v0.2-beta
|
|
*/
|
|
public Level getConsoleLevelBarrier() { return (Level) items.get("consoleLevelBarrier").get(); }
|
|
|
|
}
|