mirror of
https://github.com/mbierlee/mirage-config.git
synced 2024-11-15 04:44:01 +01:00
Add return of default values
This commit is contained in:
parent
3ae90783de
commit
3c7918c2e2
|
@ -30,6 +30,15 @@ class ConfigReadException : Exception {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by ConfigDictionary when the supplied path does not exist.
|
||||
*/
|
||||
class ConfigPathNotFoundException : Exception {
|
||||
this(string msg, string file = __FILE__, size_t line = __LINE__) {
|
||||
super(msg, file, line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by ConfigFactory instances when loading or parsing configuration fails.
|
||||
*/
|
||||
|
@ -246,19 +255,31 @@ class ConfigDictionary {
|
|||
* Although the path should be universally the same over all types of config files, some might not lend to this structure,
|
||||
* and have a more specific way of retrieving data from the config. See the examples and specific config factories for
|
||||
* more details.
|
||||
* defaultValue = (Optional) Value to return when the given configPath is invalid. When not supplied a ConfigPathNotFoundException exception is thrown.
|
||||
*
|
||||
* Throws: ConfigReadException when something goes wrong reading the config.
|
||||
* ConfigPathNotFoundException when the given path does not exist in the config.
|
||||
*
|
||||
* Returns: The value at the path in the configuration. To convert it use get!T().
|
||||
*/
|
||||
string get(string configPath) {
|
||||
auto path = new ConfigPath(configPath);
|
||||
auto node = getNodeAt(path);
|
||||
auto value = cast(ValueNode) node;
|
||||
if (value) {
|
||||
return substituteEnvironmentVariables ? substituteEnvVars(value) : value.value;
|
||||
} else {
|
||||
throw new ConfigReadException(
|
||||
"Value expected but " ~ node.nodeType ~ " found at path: " ~ createExceptionPath(
|
||||
path));
|
||||
string get(string configPath, string defaultValue = null) {
|
||||
try {
|
||||
auto path = new ConfigPath(configPath);
|
||||
auto node = getNodeAt(path);
|
||||
auto value = cast(ValueNode) node;
|
||||
if (value) {
|
||||
return substituteEnvironmentVariables ? substituteEnvVars(value) : value.value;
|
||||
} else {
|
||||
throw new ConfigReadException(
|
||||
"Value expected but " ~ node.nodeType ~ " found at path: " ~ createExceptionPath(
|
||||
path));
|
||||
}
|
||||
} catch (ConfigPathNotFoundException e) {
|
||||
if (defaultValue !is null) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,13 +287,39 @@ class ConfigDictionary {
|
|||
* Get values from the configuration and attempts to convert them to the specified type.
|
||||
*
|
||||
* Params:
|
||||
* configPath = Path to the wanted config value. See get().
|
||||
* configPath = Path to the wanted config value. See get().
|
||||
*
|
||||
* Throws: ConfigReadException when something goes wrong reading the config.
|
||||
* ConfigPathNotFoundException when the given path does not exist in the config.
|
||||
*
|
||||
* Returns: The value at the path in the configuration.
|
||||
* See_Also: get
|
||||
*/
|
||||
ConvertToType get(ConvertToType)(string configPath) {
|
||||
return get(configPath).to!ConvertToType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get values from the configuration and attempts to convert them to the specified type.
|
||||
*
|
||||
* Params:
|
||||
* configPath = Path to the wanted config value. See get().
|
||||
* defaultValue = (Optional) Value to return when the given configPath is invalid. When not supplied a ConfigPathNotFoundException exception is thrown.
|
||||
*
|
||||
* Throws: ConfigReadException when something goes wrong reading the config.
|
||||
* ConfigPathNotFoundException when the given path does not exist in the config.
|
||||
*
|
||||
* Returns: The value at the path in the configuration.
|
||||
* See_Also: get
|
||||
*/
|
||||
ConvertToType get(ConvertToType)(string configPath, ConvertToType defaultValue) {
|
||||
try {
|
||||
return get(configPath).to!ConvertToType;
|
||||
} catch (ConfigPathNotFoundException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a sub-section of the config as another config.
|
||||
*
|
||||
|
@ -294,20 +341,23 @@ class ConfigDictionary {
|
|||
}
|
||||
|
||||
private ConfigNode getNodeAt(ConfigPath path) {
|
||||
enforce!ConfigReadException(rootNode !is null, "The config is empty");
|
||||
void throwPathNotFound() {
|
||||
throw new ConfigPathNotFoundException(
|
||||
"Path does not exist: " ~ createExceptionPath(path));
|
||||
}
|
||||
|
||||
if (rootNode is null) {
|
||||
throwPathNotFound();
|
||||
}
|
||||
|
||||
auto currentNode = rootNode;
|
||||
PathSegment currentPathSegment = path.getNextSegment();
|
||||
|
||||
void throwPathNotExists() {
|
||||
throw new ConfigReadException("Path does not exist: " ~ createExceptionPath(path));
|
||||
}
|
||||
|
||||
void ifNotNullPointer(void* obj, void delegate() fn) {
|
||||
if (obj) {
|
||||
fn();
|
||||
} else {
|
||||
throwPathNotExists();
|
||||
throwPathNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,18 +365,18 @@ class ConfigDictionary {
|
|||
if (obj) {
|
||||
fn();
|
||||
} else {
|
||||
throwPathNotExists();
|
||||
throwPathNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
while (currentPathSegment !is null) {
|
||||
if (currentNode is null) {
|
||||
throwPathNotExists();
|
||||
throwPathNotFound();
|
||||
}
|
||||
|
||||
auto valueNode = cast(ValueNode) currentNode;
|
||||
if (valueNode) {
|
||||
throwPathNotExists();
|
||||
throwPathNotFound();
|
||||
}
|
||||
|
||||
auto arrayPath = cast(ArrayPathSegment) currentPathSegment;
|
||||
|
@ -485,7 +535,7 @@ version (unittest) {
|
|||
unittest {
|
||||
auto config = new ConfigDictionary();
|
||||
|
||||
assertThrown!ConfigReadException(config.get("."));
|
||||
assertThrown!ConfigPathNotFoundException(config.get("."));
|
||||
}
|
||||
|
||||
@("Get value in root with empty path")
|
||||
|
@ -586,7 +636,7 @@ version (unittest) {
|
|||
])
|
||||
);
|
||||
|
||||
assertThrown!ConfigReadException(config.get("hostname.cluster.spacey"));
|
||||
assertThrown!ConfigPathNotFoundException(config.get("hostname.cluster.spacey"));
|
||||
}
|
||||
|
||||
@("Exception is thrown when given path terminates too early")
|
||||
|
@ -604,7 +654,7 @@ version (unittest) {
|
|||
unittest {
|
||||
auto config = new ConfigDictionary(new ArrayNode());
|
||||
|
||||
assertThrown!ConfigReadException(config.get("hostname"));
|
||||
assertThrown!ConfigPathNotFoundException(config.get("hostname"));
|
||||
}
|
||||
|
||||
@("Get value from objects in array")
|
||||
|
@ -789,8 +839,19 @@ version (unittest) {
|
|||
assert(config.get("tooMuchWhiteSpace") == "$MIRAGE_CONFIG_TEST_ENV_VAR ");
|
||||
assert(config.get("notSet") == "${MIRAGE_CONFIG_NOT_SET_TEST_ENV_VAR}");
|
||||
assert(config.get("withDefault") == "$MIRAGE_CONFIG_NOT_SET_TEST_ENV_VAR:use default!");
|
||||
assert(config.get("withDefaultAndBrackets") == "${MIRAGE_CONFIG_NOT_SET_TEST_ENV_VAR:use default!}");
|
||||
assert(config.get(
|
||||
"withDefaultAndBrackets") == "${MIRAGE_CONFIG_NOT_SET_TEST_ENV_VAR:use default!}");
|
||||
assert(config.get("megaMix") == "${MIRAGE_CONFIG_TEST_ENV_VAR_TWO} ${MIRAGE_CONFIG_TEST_ENV_VAR} ${MIRAGE_CONFIG_NOT_SET_TEST_ENV_VAR:go}!");
|
||||
assert(config.get("typical") == "${MIRAGE_CONFIG_TEST_HOSTNAME:localhost}:${MIRAGE_CONFIG_TEST_PORT:8080}");
|
||||
assert(config.get(
|
||||
"typical") == "${MIRAGE_CONFIG_TEST_HOSTNAME:localhost}:${MIRAGE_CONFIG_TEST_PORT:8080}");
|
||||
}
|
||||
|
||||
@("Get with default should return default")
|
||||
unittest {
|
||||
auto config = new ConfigDictionary();
|
||||
assert(config.get("la.la.la", "not there") == "not there");
|
||||
assert(config.get!int("do.re.mi.fa.so", 42) == 42);
|
||||
}
|
||||
|
||||
//TODO: Test null nodes should gracefully fail
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue