Add support for colon as key/value separator in Java properties

This commit is contained in:
Mike Bierlee 2022-10-13 00:31:01 +03:00
parent 6d3833cbf1
commit 46fb406cad
2 changed files with 67 additions and 9 deletions

View file

@ -12,7 +12,8 @@
module mirage.java; module mirage.java;
import mirage.config : ConfigDictionary; import mirage.config : ConfigDictionary;
import mirage.keyvalue : KeyValueConfigFactory, SupportHashtagComments, SupportSemicolonComments, SupportSections, NormalizeQuotedValues; import mirage.keyvalue : KeyValueConfigFactory, SupportHashtagComments, SupportSemicolonComments,
SupportSections, NormalizeQuotedValues, SupportEqualsSeparator, SupportColonSeparator;
/** /**
* Creates configuration files from Java properties. * Creates configuration files from Java properties.
@ -21,7 +22,9 @@ class JavaPropertiesFactory : KeyValueConfigFactory!(
SupportHashtagComments.yes, SupportHashtagComments.yes,
SupportSemicolonComments.no, SupportSemicolonComments.no,
SupportSections.no, SupportSections.no,
NormalizeQuotedValues.no NormalizeQuotedValues.no,
SupportEqualsSeparator.yes,
SupportColonSeparator.yes
) { ) {
} }

View file

@ -23,6 +23,8 @@ alias SupportHashtagComments = Flag!"SupportHashtagComments";
alias SupportSemicolonComments = Flag!"SupportSemicolonComments"; alias SupportSemicolonComments = Flag!"SupportSemicolonComments";
alias SupportSections = Flag!"SupportSections"; alias SupportSections = Flag!"SupportSections";
alias NormalizeQuotedValues = Flag!"NormalizeQuotedValues"; alias NormalizeQuotedValues = Flag!"NormalizeQuotedValues";
alias SupportEqualsSeparator = Flag!"SupportEqualsSeparator";
alias SupportColonSeparator = Flag!"SupportColonSeparator";
/** /**
* A generic reusable key/value config factory that can be configured to parse * A generic reusable key/value config factory that can be configured to parse
@ -32,8 +34,11 @@ class KeyValueConfigFactory(
SupportHashtagComments supportHashtagComments = SupportHashtagComments.no, SupportHashtagComments supportHashtagComments = SupportHashtagComments.no,
SupportSemicolonComments supportSemicolonComments = SupportSemicolonComments.no, SupportSemicolonComments supportSemicolonComments = SupportSemicolonComments.no,
SupportSections supportSections = SupportSections.no, SupportSections supportSections = SupportSections.no,
NormalizeQuotedValues normalizeQuotedValues = NormalizeQuotedValues.no NormalizeQuotedValues normalizeQuotedValues = NormalizeQuotedValues.no,
SupportEqualsSeparator supportEqualsSeparator = SupportEqualsSeparator.no,
SupportColonSeparator supportColonSeparator = SupportColonSeparator.no
) : ConfigFactory { ) : ConfigFactory {
/** /**
* Parse a configuration file following the configured key/value conventions. * Parse a configuration file following the configured key/value conventions.
* *
@ -43,6 +48,8 @@ class KeyValueConfigFactory(
*/ */
override ConfigDictionary parseConfig(string contents) { override ConfigDictionary parseConfig(string contents) {
enforce!ConfigCreationException(contents !is null, "Contents cannot be null."); enforce!ConfigCreationException(contents !is null, "Contents cannot be null.");
enforce!ConfigCreationException(supportEqualsSeparator || supportColonSeparator, "No key/value separator is supported. Factory must set one either SupportEqualsSeparator or SupportColonSeparator");
auto lines = contents.lineSplitter().array; auto lines = contents.lineSplitter().array;
auto properties = new ConfigDictionary(); auto properties = new ConfigDictionary();
auto section = ""; auto section = "";
@ -80,7 +87,15 @@ class KeyValueConfigFactory(
continue; continue;
} }
auto parts = processedLine.split('='); char keyValueSplitter;
if (supportEqualsSeparator && processedLine.indexOf('=') >= 0) {
keyValueSplitter = '=';
} else if (supportColonSeparator && processedLine.indexOf(':') >= 0) {
keyValueSplitter = ':';
}
auto parts = processedLine.split(keyValueSplitter);
enforce!ConfigCreationException(parts.length <= 2, "Line has too many equals signs and cannot be parsed (L" ~ index enforce!ConfigCreationException(parts.length <= 2, "Line has too many equals signs and cannot be parsed (L" ~ index
.to!string ~ "): " ~ processedLine); .to!string ~ "): " ~ processedLine);
enforce!ConfigCreationException(parts.length == 2, "Missing value assignment (L" ~ index.to!string ~ "): " ~ processedLine); enforce!ConfigCreationException(parts.length == 2, "Missing value assignment (L" ~ index.to!string ~ "): " ~ processedLine);
@ -105,7 +120,14 @@ version (unittest) {
import std.exception : assertThrown; import std.exception : assertThrown;
import std.process : environment; import std.process : environment;
class TestKeyValueConfigFactory : KeyValueConfigFactory!() { class TestKeyValueConfigFactory : KeyValueConfigFactory!(
SupportHashtagComments.no,
SupportSemicolonComments.no,
SupportSections.no,
NormalizeQuotedValues.no,
SupportEqualsSeparator.yes,
SupportColonSeparator.no
) {
} }
@("Parse standard key/value config") @("Parse standard key/value config")
@ -123,7 +145,11 @@ version (unittest) {
unittest { unittest {
auto config = new KeyValueConfigFactory!( auto config = new KeyValueConfigFactory!(
SupportHashtagComments.yes, SupportHashtagComments.yes,
SupportSemicolonComments.yes SupportSemicolonComments.yes,
SupportSections.no,
NormalizeQuotedValues.no,
SupportEqualsSeparator.yes,
SupportColonSeparator.no
)().parseConfig(" )().parseConfig("
# this is a comment # this is a comment
; this is another comment ; this is another comment
@ -176,7 +202,11 @@ version (unittest) {
unittest { unittest {
auto config = new KeyValueConfigFactory!( auto config = new KeyValueConfigFactory!(
SupportHashtagComments.yes, SupportHashtagComments.yes,
SupportSemicolonComments.yes SupportSemicolonComments.yes,
SupportSections.no,
NormalizeQuotedValues.no,
SupportEqualsSeparator.yes,
SupportColonSeparator.no
)().parseConfig(" )().parseConfig("
server=localhost #todo: change me. default=localhost when not set. server=localhost #todo: change me. default=localhost when not set.
port=9876; I think this port = right? port=9876; I think this port = right?
@ -191,7 +221,10 @@ version (unittest) {
auto config = new KeyValueConfigFactory!( auto config = new KeyValueConfigFactory!(
SupportHashtagComments.no, SupportHashtagComments.no,
SupportSemicolonComments.yes, SupportSemicolonComments.yes,
SupportSections.yes SupportSections.yes,
NormalizeQuotedValues.no,
SupportEqualsSeparator.yes,
SupportColonSeparator.no
)().parseConfig(" )().parseConfig("
applicationName = test me! applicationName = test me!
@ -223,7 +256,9 @@ version (unittest) {
SupportHashtagComments.yes, SupportHashtagComments.yes,
SupportSemicolonComments.no, SupportSemicolonComments.no,
SupportSections.no, SupportSections.no,
NormalizeQuotedValues.yes NormalizeQuotedValues.yes,
SupportEqualsSeparator.yes,
SupportColonSeparator.no
)().parseConfig(" )().parseConfig("
baboon = \"ape\" baboon = \"ape\"
monkey = 'ape' monkey = 'ape'
@ -239,4 +274,24 @@ version (unittest) {
assert(config.get("breaksWithComments") == "'"); assert(config.get("breaksWithComments") == "'");
} }
@("Support colon as key/value separator")
unittest {
auto config = new KeyValueConfigFactory!(
SupportHashtagComments.no,
SupportSemicolonComments.no,
SupportSections.no,
NormalizeQuotedValues.no,
SupportEqualsSeparator.yes,
SupportColonSeparator.yes
)().parseConfig("
one = here
two: also here
");
assert(config.get("one") == "here");
assert(config.get("two") == "also here");
assertThrown!ConfigCreationException(new KeyValueConfigFactory!()().parseConfig("a=b")); // No separator is configured
}
} }