[CORDA-1993]: Replace reflection-based NodeConfiguration parsing with versioned property-based parsing mechanism. (#4132)

This commit is contained in:
Michele Sollecito
2018-11-08 15:56:00 +00:00
committed by GitHub
parent 9277042db8
commit 6c749889d0
34 changed files with 1161 additions and 513 deletions

View File

@ -4,6 +4,7 @@ import com.typesafe.config.Config
import com.typesafe.config.ConfigException
import com.typesafe.config.ConfigObject
import com.typesafe.config.ConfigValue
import com.typesafe.config.ConfigValueFactory
import net.corda.common.configuration.parsing.internal.versioned.VersionExtractor
import net.corda.common.validation.internal.Validated
import net.corda.common.validation.internal.Validated.Companion.invalid
@ -24,7 +25,7 @@ object Configuration {
/**
* Describes a [Config] hiding sensitive data.
*/
fun describe(configuration: Config): ConfigValue
fun describe(configuration: Config, serialiseValue: (Any) -> ConfigValue = { value -> ConfigValueFactory.fromAnyRef(value.toString()) }): ConfigValue?
}
object Value {
@ -112,6 +113,11 @@ object Configuration {
*/
interface Definition<TYPE> : Configuration.Property.Metadata, Configuration.Validator, Configuration.Value.Extractor<TYPE>, Configuration.Describer, Configuration.Value.Parser<TYPE> {
/**
* Validates target [Config] with default [Configuration.Validation.Options].
*/
fun validate(target: Config): Valid<Config> = validate(target, Configuration.Validation.Options.defaults)
override fun isSpecifiedBy(configuration: Config): Boolean = configuration.hasPath(key)
/**
@ -120,9 +126,9 @@ object Configuration {
interface Required<TYPE> : Definition<TYPE> {
/**
* Returns an optional property with given [defaultValue]. This property does not produce errors in case the value is unspecified, returning the [defaultValue] instead.
* Returns an optional property. This property does not produce errors in case the value is unspecified.
*/
fun optional(defaultValue: TYPE? = null): Definition<TYPE?>
fun optional(): Optional<TYPE>
}
/**
@ -136,6 +142,17 @@ object Configuration {
fun list(): Required<List<TYPE>>
}
/**
* Defines a property that might be missing, resulting in a null value.
*/
interface Optional<TYPE> : Definition<TYPE?> {
/**
* Allows to specify a [defaultValue], returning a required [Configuration.Property.Definition].
*/
fun withDefaultValue(defaultValue: TYPE): Definition<TYPE>
}
/**
* Default property definition, required and single-value.
*/
@ -219,7 +236,7 @@ object Configuration {
/**
* Returns a [Configuration.Property.Definition.Standard] with value of type [ENUM].
* This property expects the exact [ENUM] value specified as text for the relevant key.
* This property expects a value in the configuration matching one of the cases of [ENUM], as text, in uppercase.
*/
fun <ENUM : Enum<ENUM>> enum(key: String, enumClass: KClass<ENUM>, sensitive: Boolean = false): Standard<ENUM> = StandardProperty(key, enumClass.java.simpleName, { conf: Config, propertyKey: String -> conf.getEnum(enumClass.java, propertyKey) }, { conf: Config, propertyKey: String -> conf.getEnumList(enumClass.java, propertyKey) }, sensitive)
}
@ -246,6 +263,13 @@ object Configuration {
*/
val properties: Set<Property.Definition<*>>
/**
* Validates target [Config] with default [Configuration.Validation.Options].
*/
fun validate(target: Config): Valid<Config> = validate(target, Configuration.Validation.Options.defaults)
override fun describe(configuration: Config, serialiseValue: (Any) -> ConfigValue): ConfigValue
companion object {
/**
@ -270,7 +294,7 @@ object Configuration {
* A [Configuration.Schema] that is also able to parse a raw [Config] object into a [VALUE].
* It is an abstract class to allow extension with delegated properties e.g., object Settings: Specification() { val address by string().optional("localhost:8080") }.
*/
abstract class Specification<VALUE>(name: String?, private val prefix: String? = null) : Configuration.Schema, Configuration.Value.Parser<VALUE> {
abstract class Specification<VALUE>(override val name: String, private val prefix: String? = null) : Configuration.Schema, Configuration.Value.Parser<VALUE> {
private val mutableProperties = mutableSetOf<Property.Definition<*>>()
@ -321,17 +345,20 @@ object Configuration {
/**
* Returns a delegate for a [Configuration.Property.Definition.Standard] of type [ENUM].
* This property expects the exact [ENUM] value specified as text for the relevant key.
* This property expects a value in the configuration matching one of the cases of [ENUM], as text, in uppercase.
*/
fun <ENUM : Enum<ENUM>> enum(key: String? = null, enumClass: KClass<ENUM>, sensitive: Boolean = false): PropertyDelegate.Standard<ENUM> = PropertyDelegate.enum(key, prefix, enumClass, sensitive) { mutableProperties.add(it) }
override val name: String? get() = schema.name
/**
* @see enum
*/
fun <ENUM : Enum<ENUM>> enum(enumClass: KClass<ENUM>, sensitive: Boolean = false): PropertyDelegate.Standard<ENUM> = enum(key = null, enumClass = enumClass, sensitive = sensitive)
override fun description() = schema.description()
override fun validate(target: Config, options: Validation.Options?) = schema.validate(target, options)
override fun validate(target: Config, options: Validation.Options) = schema.validate(target, options)
override fun describe(configuration: Config) = schema.describe(configuration)
override fun describe(configuration: Config, serialiseValue: (Any) -> ConfigValue) = schema.describe(configuration, serialiseValue)
final override fun parse(configuration: Config, options: Configuration.Validation.Options): Valid<VALUE> = validate(configuration, options).mapValid(::parseValid)
@ -397,9 +424,11 @@ object Configuration {
val containingPathAsString: String = containingPath.joinToString(".")
/**
* [pathstr] joined by "." characters.
* [path] joined by "." characters.
*/
val pathAsString: String = path.joinToString(".")
val pathAsString: String get() = path.joinToString(".")
internal fun withContainingPathPrefix(vararg containingPath: String): Error = withContainingPath(*(containingPath.toList() + this.containingPath).toTypedArray())
internal abstract fun withContainingPath(vararg containingPath: String): Error
@ -415,12 +444,14 @@ object Configuration {
*/
class WrongType private constructor(override val keyName: String, override val typeName: String, message: String, containingPath: List<String> = emptyList()) : Configuration.Validation.Error(keyName, typeName, message, containingPath) {
internal companion object {
companion object {
internal fun of(message: String, keyName: String = UNKNOWN, typeName: String = UNKNOWN, containingPath: List<String> = emptyList()): WrongType = contextualize(keyName, containingPath).let { (key, path) -> WrongType(key, typeName, message, path) }
fun of(message: String, keyName: String? = null, typeName: String = UNKNOWN, containingPath: List<String> = emptyList()): WrongType = contextualize(keyName ?: UNKNOWN, containingPath).let { (key, path) -> WrongType(key, typeName, message, path) }
fun forKey(keyName: String, expectedTypeName: String, actualTypeName: String): WrongType = of("$keyName has type ${actualTypeName.toUpperCase()} rather than ${expectedTypeName.toUpperCase()}")
}
override fun withContainingPath(vararg containingPath: String) = WrongType(keyName, typeName, message, containingPath.toList() + this.containingPath)
override fun withContainingPath(vararg containingPath: String) = WrongType(keyName, typeName, message, containingPath.toList())
override fun with(keyName: String, typeName: String): WrongType = WrongType.of(message, keyName, typeName, containingPath)
}
@ -430,12 +461,14 @@ object Configuration {
*/
class MissingValue private constructor(override val keyName: String, override val typeName: String, message: String, containingPath: List<String> = emptyList()) : Configuration.Validation.Error(keyName, typeName, message, containingPath) {
internal companion object {
companion object {
internal fun of(message: String, keyName: String = UNKNOWN, typeName: String = UNKNOWN, containingPath: List<String> = emptyList()): MissingValue = contextualize(keyName, containingPath).let { (key, path) -> MissingValue(key, typeName, message, path) }
fun of(message: String, keyName: String? = null, typeName: String = UNKNOWN, containingPath: List<String> = emptyList()): MissingValue = contextualize(keyName ?: UNKNOWN, containingPath).let { (key, path) -> MissingValue(key, typeName, message, path) }
fun forKey(keyName: String): MissingValue = of("No configuration setting found for key '$keyName'", keyName)
}
override fun withContainingPath(vararg containingPath: String) = MissingValue(keyName, typeName, message, containingPath.toList() + this.containingPath)
override fun withContainingPath(vararg containingPath: String) = MissingValue(keyName, typeName, message, containingPath.toList())
override fun with(keyName: String, typeName: String): MissingValue = MissingValue.of(message, keyName, typeName, containingPath)
}
@ -445,12 +478,12 @@ object Configuration {
*/
class BadValue private constructor(override val keyName: String, override val typeName: String, message: String, containingPath: List<String> = emptyList()) : Configuration.Validation.Error(keyName, typeName, message, containingPath) {
internal companion object {
companion object {
internal fun of(message: String, keyName: String = UNKNOWN, typeName: String = UNKNOWN, containingPath: List<String> = emptyList()): BadValue = contextualize(keyName, containingPath).let { (key, path) -> BadValue(key, typeName, message, path) }
fun of(message: String, keyName: String? = null, typeName: String = UNKNOWN, containingPath: List<String> = emptyList()): BadValue = contextualize(keyName ?: UNKNOWN, containingPath).let { (key, path) -> BadValue(key, typeName, message, path) }
}
override fun withContainingPath(vararg containingPath: String) = BadValue(keyName, typeName, message, containingPath.toList() + this.containingPath)
override fun withContainingPath(vararg containingPath: String) = BadValue(keyName, typeName, message, containingPath.toList())
override fun with(keyName: String, typeName: String): BadValue = BadValue.of(message, keyName, typeName, containingPath)
}
@ -460,12 +493,12 @@ object Configuration {
*/
class BadPath private constructor(override val keyName: String, override val typeName: String, message: String, containingPath: List<String> = emptyList()) : Configuration.Validation.Error(keyName, typeName, message, containingPath) {
internal companion object {
companion object {
internal fun of(message: String, keyName: String = UNKNOWN, typeName: String = UNKNOWN, containingPath: List<String> = emptyList()): BadPath = contextualize(keyName, containingPath).let { (key, path) -> BadPath(key, typeName, message, path) }
fun of(message: String, keyName: String? = null, typeName: String = UNKNOWN, containingPath: List<String> = emptyList()): BadPath = contextualize(keyName ?: UNKNOWN, containingPath).let { (key, path) -> BadPath(key, typeName, message, path) }
}
override fun withContainingPath(vararg containingPath: String) = BadPath(keyName, typeName, message, containingPath.toList() + this.containingPath)
override fun withContainingPath(vararg containingPath: String) = BadPath(keyName, typeName, message, containingPath.toList())
override fun with(keyName: String, typeName: String): BadPath = BadPath.of(message, keyName, typeName, containingPath)
}
@ -475,12 +508,12 @@ object Configuration {
*/
class MalformedStructure private constructor(override val keyName: String, override val typeName: String, message: String, containingPath: List<String> = emptyList()) : Configuration.Validation.Error(keyName, typeName, message, containingPath) {
internal companion object {
companion object {
internal fun of(message: String, keyName: String = UNKNOWN, typeName: String = UNKNOWN, containingPath: List<String> = emptyList()): MalformedStructure = contextualize(keyName, containingPath).let { (key, path) -> MalformedStructure(key, typeName, message, path) }
fun of(message: String, keyName: String? = null, typeName: String = UNKNOWN, containingPath: List<String> = emptyList()): MalformedStructure = contextualize(keyName ?: UNKNOWN, containingPath).let { (key, path) -> MalformedStructure(key, typeName, message, path) }
}
override fun withContainingPath(vararg containingPath: String) = MalformedStructure(keyName, typeName, message, containingPath.toList() + this.containingPath)
override fun withContainingPath(vararg containingPath: String) = MalformedStructure(keyName, typeName, message, containingPath.toList())
override fun with(keyName: String, typeName: String): MalformedStructure = MalformedStructure.of(message, keyName, typeName, containingPath)
}
@ -490,16 +523,14 @@ object Configuration {
*/
class Unknown private constructor(override val keyName: String, containingPath: List<String> = emptyList()) : Configuration.Validation.Error(keyName, null, message(keyName), containingPath) {
internal companion object {
companion object {
private fun message(keyName: String) = "Unknown property \"$keyName\"."
private fun message(keyName: String) = "Unknown property \'$keyName\'"
internal fun of(keyName: String = UNKNOWN, containingPath: List<String> = emptyList()): Unknown = contextualize(keyName, containingPath).let { (key, path) -> Unknown(key, path) }
fun of(keyName: String = UNKNOWN, containingPath: List<String> = emptyList()): Unknown = contextualize(keyName, containingPath).let { (key, path) -> Unknown(key, path) }
}
override val message = message(pathAsString)
override fun withContainingPath(vararg containingPath: String) = Unknown(keyName, containingPath.toList() + this.containingPath)
override fun withContainingPath(vararg containingPath: String) = Unknown(keyName, containingPath.toList())
override fun with(keyName: String, typeName: String): Unknown = Unknown.of(keyName, containingPath)
}
@ -509,12 +540,12 @@ object Configuration {
*/
class UnsupportedVersion private constructor(val version: Int, containingPath: List<String> = emptyList()) : Configuration.Validation.Error(null, null, "Unknown configuration version $version.", containingPath) {
internal companion object {
companion object {
internal fun of(version: Int): UnsupportedVersion = UnsupportedVersion(version)
fun of(version: Int): UnsupportedVersion = UnsupportedVersion(version)
}
override fun withContainingPath(vararg containingPath: String) = UnsupportedVersion(version, containingPath.toList() + this.containingPath)
override fun withContainingPath(vararg containingPath: String) = UnsupportedVersion(version, containingPath.toList())
override fun with(keyName: String, typeName: String): UnsupportedVersion = this
}
@ -526,16 +557,16 @@ object Configuration {
/**
* Defines the contract from extracting a specification version from a [Config] object.
*/
interface Extractor : Configuration.Value.Parser<Int?> {
interface Extractor : Configuration.Value.Parser<Int> {
companion object {
const val DEFAULT_VERSION_VALUE = 1
/**
* Returns a [Configuration.Version.Extractor] that reads the value from given [versionKey], defaulting to [versionDefaultValue] when [versionKey] is unspecified.
* Returns a [Configuration.Version.Extractor] that reads the value from given [versionPath], defaulting to [versionDefaultValue] when [versionPath] is unspecified.
*/
fun fromKey(versionKey: String, versionDefaultValue: Int? = DEFAULT_VERSION_VALUE): Configuration.Version.Extractor = VersionExtractor(versionKey, versionDefaultValue)
fun fromPath(versionPath: String, versionDefaultValue: Int = DEFAULT_VERSION_VALUE): Configuration.Version.Extractor = VersionExtractor(versionPath, versionDefaultValue)
}
}
}

View File

@ -1,13 +1,17 @@
package net.corda.common.configuration.parsing.internal
import com.typesafe.config.*
import com.typesafe.config.Config
import com.typesafe.config.ConfigException
import com.typesafe.config.ConfigObject
import com.typesafe.config.ConfigValue
import com.typesafe.config.ConfigValueFactory
import net.corda.common.validation.internal.Validated
import net.corda.common.validation.internal.Validated.Companion.invalid
import net.corda.common.validation.internal.Validated.Companion.valid
internal class LongProperty(key: String, sensitive: Boolean = false) : StandardProperty<Long>(key, Long::class.javaObjectType.simpleName, Config::getLong, Config::getLongList, sensitive) {
override fun validate(target: Config, options: Configuration.Validation.Options?): Valid<Config> {
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> {
val validated = super.validate(target, options)
if (validated.isValid && target.getValue(key).unwrapped().toString().contains(".")) {
@ -17,7 +21,7 @@ internal class LongProperty(key: String, sensitive: Boolean = false) : StandardP
}
}
internal open class StandardProperty<TYPE>(override val key: String, typeNameArg: String, private val extractSingleValue: (Config, String) -> TYPE, internal val extractListValue: (Config, String) -> List<TYPE>, override val isSensitive: Boolean = false, final override val schema: Configuration.Schema? = null) : Configuration.Property.Definition.Standard<TYPE> {
internal open class StandardProperty<TYPE : Any>(override val key: String, typeNameArg: String, private val extractSingleValue: (Config, String) -> TYPE, internal val extractListValue: (Config, String) -> List<TYPE>, override val isSensitive: Boolean = false, final override val schema: Configuration.Schema? = null) : Configuration.Property.Definition.Standard<TYPE> {
override fun valueIn(configuration: Config) = extractSingleValue.invoke(configuration, key)
@ -25,21 +29,21 @@ internal open class StandardProperty<TYPE>(override val key: String, typeNameArg
override fun <MAPPED : Any> mapValid(mappedTypeName: String, convert: (TYPE) -> Valid<MAPPED>): Configuration.Property.Definition.Standard<MAPPED> = FunctionalProperty(this, mappedTypeName, extractListValue, convert)
override fun optional(defaultValue: TYPE?): Configuration.Property.Definition<TYPE?> = OptionalProperty(this, defaultValue)
override fun optional(): Configuration.Property.Definition.Optional<TYPE> = OptionalDelegatedProperty(this)
override fun list(): Configuration.Property.Definition.Required<List<TYPE>> = ListProperty(this)
override fun describe(configuration: Config): ConfigValue {
override fun describe(configuration: Config, serialiseValue: (Any) -> ConfigValue): ConfigValue {
if (isSensitive) {
return ConfigValueFactory.fromAnyRef(Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER)
return valueDescription(Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER, serialiseValue)
}
return schema?.describe(configuration.getConfig(key)) ?: ConfigValueFactory.fromAnyRef(valueIn(configuration))
return schema?.describe(configuration.getConfig(key), serialiseValue) ?: valueDescription(valueIn(configuration), serialiseValue)
}
override val isMandatory = true
override fun validate(target: Config, options: Configuration.Validation.Options?): Valid<Config> {
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> {
val errors = mutableSetOf<Configuration.Validation.Error>()
errors += errorsWhenExtractingValue(target)
@ -47,7 +51,7 @@ internal open class StandardProperty<TYPE>(override val key: String, typeNameArg
schema?.let { nestedSchema ->
val nestedConfig: Config? = target.getConfig(key)
nestedConfig?.let {
errors += nestedSchema.validate(nestedConfig, options).errors.map { error -> error.withContainingPath(*key.split(".").toTypedArray()) }
errors += nestedSchema.validate(nestedConfig, options).errors.map { error -> error.withContainingPathPrefix(*key.split(".").toTypedArray()) }
}
}
}
@ -57,63 +61,63 @@ internal open class StandardProperty<TYPE>(override val key: String, typeNameArg
override fun toString() = "\"$key\": \"$typeName\""
}
private class ListProperty<TYPE>(delegate: StandardProperty<TYPE>) : RequiredDelegatedProperty<List<TYPE>, StandardProperty<TYPE>>(delegate) {
private class ListProperty<TYPE : Any>(delegate: StandardProperty<TYPE>) : RequiredDelegatedProperty<List<TYPE>, StandardProperty<TYPE>>(delegate) {
override val typeName: String = "List<${delegate.typeName}>"
override fun valueIn(configuration: Config): List<TYPE> = delegate.extractListValue.invoke(configuration, key)
override fun validate(target: Config, options: Configuration.Validation.Options?): Valid<Config> {
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> {
val errors = mutableSetOf<Configuration.Validation.Error>()
errors += errorsWhenExtractingValue(target)
if (errors.isEmpty()) {
delegate.schema?.let { schema ->
errors += valueIn(target).asSequence().map { element -> element as ConfigObject }.map(ConfigObject::toConfig).mapIndexed { index, targetConfig -> schema.validate(targetConfig, options).errors.map { error -> error.withContainingPath(key, "[$index]") } }.reduce { one, other -> one + other }
errors += valueIn(target).asSequence().map { element -> element as ConfigObject }.map(ConfigObject::toConfig).mapIndexed { index, targetConfig -> schema.validate(targetConfig, options).errors.map { error -> error.withContainingPath(*error.containingPath(index).toTypedArray()) } }.fold(emptyList<Configuration.Validation.Error>()) { one, other -> one + other }.toSet()
}
}
return Validated.withResult(target, errors)
}
override fun describe(configuration: Config): ConfigValue {
override fun describe(configuration: Config, serialiseValue: (Any) -> ConfigValue): ConfigValue {
if (isSensitive) {
return ConfigValueFactory.fromAnyRef(Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER)
return valueDescription(Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER, serialiseValue)
}
return when {
delegate.schema != null -> {
val elementsDescription = valueIn(configuration).asSequence().map { it as ConfigObject }.map(ConfigObject::toConfig).map { delegate.schema.describe(it, serialiseValue) }.toList()
ConfigValueFactory.fromIterable(elementsDescription)
}
else -> valueDescription(valueIn(configuration), serialiseValue)
}
}
private fun Configuration.Validation.Error.containingPath(index: Int): List<String> {
val newContainingPath = listOf(key, "[$index]")
return when {
containingPath.size > 1 -> newContainingPath + containingPath.subList(1, containingPath.size)
else -> newContainingPath
}
return delegate.schema?.let { schema -> ConfigValueFactory.fromAnyRef(valueIn(configuration).asSequence().map { element -> element as ConfigObject }.map(ConfigObject::toConfig).map { schema.describe(it) }.toList()) } ?: ConfigValueFactory.fromAnyRef(valueIn(configuration))
}
}
private class OptionalProperty<TYPE>(delegate: Configuration.Property.Definition.Required<TYPE>, private val defaultValue: TYPE?) : DelegatedProperty<TYPE?, Configuration.Property.Definition.Required<TYPE>>(delegate) {
private class OptionalPropertyWithDefault<TYPE : Any>(delegate: Configuration.Property.Definition.Optional<TYPE>, private val defaultValue: TYPE) : DelegatedProperty<TYPE, Configuration.Property.Definition.Optional<TYPE>>(delegate) {
override val isMandatory: Boolean = false
override val typeName: String = "${super.typeName}?"
override val typeName: String = delegate.typeName.removeSuffix("?")
override fun describe(configuration: Config) = delegate.describe(configuration)
override fun describe(configuration: Config, serialiseValue: (Any) -> ConfigValue): ConfigValue? = delegate.describe(configuration, serialiseValue) ?: valueDescription(if (isSensitive) Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER else defaultValue, serialiseValue)
override fun valueIn(configuration: Config): TYPE? {
override fun valueIn(configuration: Config): TYPE = delegate.valueIn(configuration) ?: defaultValue
return when {
isSpecifiedBy(configuration) -> delegate.valueIn(configuration)
else -> defaultValue
}
}
override fun validate(target: Config, options: Configuration.Validation.Options?): Valid<Config> {
val result = delegate.validate(target, options)
val error = result.errors.asSequence().filterIsInstance<Configuration.Validation.Error.MissingValue>().singleOrNull()
return when {
error != null -> if (result.errors.size > 1) result else valid(target)
else -> result
}
}
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> = delegate.validate(target, options)
}
private class FunctionalProperty<TYPE, MAPPED : Any>(delegate: Configuration.Property.Definition.Standard<TYPE>, private val mappedTypeName: String, internal val extractListValue: (Config, String) -> List<TYPE>, private val convert: (TYPE) -> Valid<MAPPED>) : RequiredDelegatedProperty<MAPPED, Configuration.Property.Definition.Standard<TYPE>>(delegate), Configuration.Property.Definition.Standard<MAPPED> {
override fun valueIn(configuration: Config) = convert.invoke(delegate.valueIn(configuration)).valueOrThrow()
override fun valueIn(configuration: Config) = convert.invoke(delegate.valueIn(configuration)).orThrow()
override val typeName: String = if (super.typeName == "#$mappedTypeName") super.typeName else "$mappedTypeName(${super.typeName})"
@ -121,7 +125,7 @@ private class FunctionalProperty<TYPE, MAPPED : Any>(delegate: Configuration.Pro
override fun list(): Configuration.Property.Definition.Required<List<MAPPED>> = FunctionalListProperty(this)
override fun validate(target: Config, options: Configuration.Validation.Options?): Valid<Config> {
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> {
val errors = mutableSetOf<Configuration.Validation.Error>()
errors += delegate.validate(target, options).errors
@ -131,7 +135,7 @@ private class FunctionalProperty<TYPE, MAPPED : Any>(delegate: Configuration.Pro
return Validated.withResult(target, errors)
}
override fun describe(configuration: Config) = delegate.describe(configuration)
override fun describe(configuration: Config, serialiseValue: (Any) -> ConfigValue) = delegate.describe(configuration, serialiseValue)
}
private class FunctionalListProperty<RAW, TYPE : Any>(delegate: FunctionalProperty<RAW, TYPE>) : RequiredDelegatedProperty<List<TYPE>, FunctionalProperty<RAW, TYPE>>(delegate) {
@ -140,7 +144,7 @@ private class FunctionalListProperty<RAW, TYPE : Any>(delegate: FunctionalProper
override fun valueIn(configuration: Config): List<TYPE> = delegate.extractListValue.invoke(configuration, key).asSequence().map { configObject(key to ConfigValueFactory.fromAnyRef(it)) }.map(ConfigObject::toConfig).map(delegate::valueIn).toList()
override fun validate(target: Config, options: Configuration.Validation.Options?): Valid<Config> {
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> {
val list = try {
delegate.extractListValue.invoke(target, key)
@ -151,16 +155,24 @@ private class FunctionalListProperty<RAW, TYPE : Any>(delegate: FunctionalProper
throw e
}
}
val errors = list.asSequence().map { configObject(key to ConfigValueFactory.fromAnyRef(it)) }.mapIndexed { index, value -> delegate.validate(value.toConfig(), options).errors.map { error -> error.withContainingPath(key, "[$index]") } }.reduce { one, other -> one + other }.toSet()
val errors = list.asSequence().map { configObject(key to ConfigValueFactory.fromAnyRef(it)) }.mapIndexed { index, value -> delegate.validate(value.toConfig(), options).errors.map { error -> error.withContainingPath(*error.containingPath(index).toTypedArray()) } }.fold(emptyList<Configuration.Validation.Error>()) { one, other -> one + other }.toSet()
return Validated.withResult(target, errors)
}
override fun describe(configuration: Config): ConfigValue {
private fun Configuration.Validation.Error.containingPath(index: Int): List<String> {
val newContainingPath = listOf(key, "[$index]")
return when {
containingPath.size > 1 -> newContainingPath + containingPath.subList(1, containingPath.size)
else -> newContainingPath
}
}
override fun describe(configuration: Config, serialiseValue: (Any) -> ConfigValue): ConfigValue {
if (isSensitive) {
return ConfigValueFactory.fromAnyRef(Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER)
return valueDescription(Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER, serialiseValue)
}
return delegate.schema?.let { schema -> ConfigValueFactory.fromAnyRef(valueIn(configuration).asSequence().map { element -> element as ConfigObject }.map(ConfigObject::toConfig).map { schema.describe(it) }.toList()) } ?: ConfigValueFactory.fromAnyRef(valueIn(configuration))
return delegate.schema?.let { schema -> valueDescription(valueIn(configuration).asSequence().map { element -> valueDescription(element, serialiseValue) }.map { it as ConfigObject }.map(ConfigObject::toConfig).map { schema.describe(it, serialiseValue) }.toList(), serialiseValue) } ?: valueDescription(valueIn(configuration), serialiseValue)
}
}
@ -169,12 +181,45 @@ private abstract class DelegatedProperty<TYPE, DELEGATE : Configuration.Property
final override fun toString() = "\"$key\": \"$typeName\""
}
private abstract class RequiredDelegatedProperty<TYPE, DELEGATE : Configuration.Property.Definition.Required<*>>(delegate: DELEGATE) : DelegatedProperty<TYPE, DELEGATE>(delegate), Configuration.Property.Definition.Required<TYPE> {
private class OptionalDelegatedProperty<TYPE : Any>(private val delegate: Configuration.Property.Definition<TYPE>) : Configuration.Property.Metadata by delegate, Configuration.Property.Definition.Optional<TYPE> {
final override fun optional(defaultValue: TYPE?): Configuration.Property.Definition<TYPE?> = OptionalProperty(this, defaultValue)
override val isMandatory: Boolean = false
override val typeName: String = "${delegate.typeName}?"
override fun describe(configuration: Config, serialiseValue: (Any) -> ConfigValue) = if (isSpecifiedBy(configuration)) delegate.describe(configuration, serialiseValue) else null
override fun valueIn(configuration: Config): TYPE? {
return when {
isSpecifiedBy(configuration) -> delegate.valueIn(configuration)
else -> null
}
}
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> {
val result = delegate.validate(target, options)
val errors = result.errors
val missingValueError = errors.asSequence().filterIsInstance<Configuration.Validation.Error.MissingValue>().filter { it.pathAsString == key }.singleOrNull()
return when {
missingValueError != null -> if (errors.size > 1) result else valid(target)
else -> result
}
}
override fun withDefaultValue(defaultValue: TYPE): Configuration.Property.Definition<TYPE> = OptionalPropertyWithDefault(this, defaultValue)
override fun toString() = "\"$key\": \"$typeName\""
}
private fun ConfigException.toValidationError(keyName: String, typeName: String): Configuration.Validation.Error {
private abstract class RequiredDelegatedProperty<TYPE : Any, DELEGATE : Configuration.Property.Definition.Required<*>>(delegate: DELEGATE) : DelegatedProperty<TYPE, DELEGATE>(delegate), Configuration.Property.Definition.Required<TYPE> {
final override fun optional(): Configuration.Property.Definition.Optional<TYPE> = OptionalDelegatedProperty(this)
}
fun ConfigException.toValidationError(keyName: String? = null, typeName: String): Configuration.Validation.Error {
val toError = when (this) {
is ConfigException.Missing -> Configuration.Validation.Error.MissingValue.Companion::of
@ -202,4 +247,6 @@ private fun Configuration.Property.Definition<*>.errorsWhenExtractingValue(targe
private val expectedExceptionTypes = setOf(ConfigException.Missing::class, ConfigException.WrongType::class, ConfigException.BadValue::class, ConfigException.BadPath::class, ConfigException.Parse::class)
private fun isErrorExpected(error: ConfigException) = expectedExceptionTypes.any { expected -> expected.isInstance(error) }
private fun isErrorExpected(error: ConfigException) = expectedExceptionTypes.any { expected -> expected.isInstance(error) }
private fun valueDescription(value: Any, serialiseValue: (Any) -> ConfigValue) = serialiseValue.invoke(value)

View File

@ -16,10 +16,12 @@ internal class Schema(override val name: String?, unorderedProperties: Iterable<
}
}
override fun validate(target: Config, options: Configuration.Validation.Options?): Valid<Config> {
override fun validate(target: Config, options: Configuration.Validation.Options): Valid<Config> {
val propertyErrors = properties.flatMap { property -> property.validate(target, options).errors }.toMutableSet()
if (options?.strict == true) {
val propertyErrors = properties.flatMap { property ->
property.validate(target, options).errors
}.toMutableSet()
if (options.strict) {
val unknownKeys = target.root().keys - properties.map(Configuration.Property.Definition<*>::key)
propertyErrors += unknownKeys.map { Configuration.Validation.Error.Unknown.of(it) }
}
@ -45,9 +47,9 @@ internal class Schema(override val name: String?, unorderedProperties: Iterable<
return description.toString()
}
override fun describe(configuration: Config): ConfigValue {
override fun describe(configuration: Config, serialiseValue: (Any) -> ConfigValue): ConfigValue {
return properties.asSequence().map { it.key to it.describe(configuration) }.fold(configObject()) { config, (key, value) -> config.withValue(key, value) }
return properties.asSequence().map { it.key to it.describe(configuration, serialiseValue) }.filter { it.second != null }.fold(configObject()) { config, (key, value) -> config.withValue(key, value) }
}
override fun equals(other: Any?): Boolean {

View File

@ -14,7 +14,7 @@ interface PropertyDelegate<TYPE> {
operator fun provideDelegate(thisRef: Any?, property: KProperty<*>): ReadOnlyProperty<Any?, Configuration.Property.Definition.Required<TYPE>>
fun optional(defaultValue: TYPE? = null): PropertyDelegate<TYPE?>
fun optional(): PropertyDelegate.Optional<TYPE>
}
interface Single<TYPE> {
@ -24,6 +24,13 @@ interface PropertyDelegate<TYPE> {
fun list(): Required<List<TYPE>>
}
interface Optional<TYPE> {
operator fun provideDelegate(thisRef: Any?, property: KProperty<*>): ReadOnlyProperty<Any?, Configuration.Property.Definition.Optional<TYPE>>
fun withDefaultValue(defaultValue: TYPE): PropertyDelegate<TYPE>
}
interface Standard<TYPE> : Required<TYPE>, Single<TYPE> {
override operator fun provideDelegate(thisRef: Any?, property: KProperty<*>): ReadOnlyProperty<Any?, Configuration.Property.Definition.Standard<TYPE>>
@ -67,35 +74,52 @@ private class PropertyDelegateImpl<TYPE>(private val key: String?, private val p
}
}
override fun list(): PropertyDelegate.Required<List<TYPE>> = ListPropertyDelegateImpl(key, sensitive, addToProperties, { k, s -> construct.invoke(k, s).list() })
override fun list(): PropertyDelegate.Required<List<TYPE>> = ListPropertyDelegateImpl(key, prefix, sensitive, addToProperties, { k, s -> construct.invoke(k, s).list() })
override fun optional(defaultValue: TYPE?): PropertyDelegate<TYPE?> = OptionalPropertyDelegateImpl(key, sensitive, addToProperties, { k, s -> construct.invoke(k, s).optional(defaultValue) })
override fun optional(): PropertyDelegate.Optional<TYPE> = OptionalPropertyDelegateImpl(key, prefix, sensitive, addToProperties, { k, s -> construct.invoke(k, s).optional() })
override fun <MAPPED : Any> mapValid(mappedTypeName: String, convert: (TYPE) -> Valid<MAPPED>): PropertyDelegate.Standard<MAPPED> = PropertyDelegateImpl(key, prefix, sensitive, addToProperties, { k, s -> construct.invoke(k, s).mapValid(mappedTypeName) { value -> convert.invoke(value) } })
}
private class OptionalPropertyDelegateImpl<TYPE>(private val key: String?, private val sensitive: Boolean = false, private val addToProperties: (Configuration.Property.Definition<*>) -> Unit, private val construct: (String, Boolean) -> Configuration.Property.Definition<TYPE?>) : PropertyDelegate<TYPE?> {
private class OptionalPropertyDelegateImpl<TYPE>(private val key: String?, private val prefix: String?, private val sensitive: Boolean = false, private val addToProperties: (Configuration.Property.Definition<*>) -> Unit, private val construct: (String, Boolean) -> Configuration.Property.Definition.Optional<TYPE>) : PropertyDelegate.Optional<TYPE> {
override operator fun provideDelegate(thisRef: Any?, property: KProperty<*>): ReadOnlyProperty<Any?, Configuration.Property.Definition<TYPE?>> {
override operator fun provideDelegate(thisRef: Any?, property: KProperty<*>): ReadOnlyProperty<Any?, Configuration.Property.Definition.Optional<TYPE>> {
val prop = construct.invoke(key ?: property.name, sensitive).also(addToProperties)
return object : ReadOnlyProperty<Any?, Configuration.Property.Definition<TYPE?>> {
val shortName = key ?: property.name
val prop = construct.invoke(prefix?.let { "$prefix.$shortName" } ?: shortName, sensitive).also(addToProperties)
return object : ReadOnlyProperty<Any?, Configuration.Property.Definition.Optional<TYPE>> {
override fun getValue(thisRef: Any?, property: KProperty<*>): Configuration.Property.Definition<TYPE?> = prop
override fun getValue(thisRef: Any?, property: KProperty<*>): Configuration.Property.Definition.Optional<TYPE> = prop
}
}
override fun withDefaultValue(defaultValue: TYPE): PropertyDelegate<TYPE> = OptionalWithDefaultPropertyDelegateImpl(key, prefix, sensitive, addToProperties, { k, s -> construct.invoke(k, s).withDefaultValue(defaultValue) })
}
private class OptionalWithDefaultPropertyDelegateImpl<TYPE>(private val key: String?, private val prefix: String?, private val sensitive: Boolean = false, private val addToProperties: (Configuration.Property.Definition<*>) -> Unit, private val construct: (String, Boolean) -> Configuration.Property.Definition<TYPE>) : PropertyDelegate<TYPE> {
override operator fun provideDelegate(thisRef: Any?, property: KProperty<*>): ReadOnlyProperty<Any?, Configuration.Property.Definition<TYPE>> {
val shortName = key ?: property.name
val prop = construct.invoke(prefix?.let { "$prefix.$shortName" } ?: shortName, sensitive).also(addToProperties)
return object : ReadOnlyProperty<Any?, Configuration.Property.Definition<TYPE>> {
override fun getValue(thisRef: Any?, property: KProperty<*>): Configuration.Property.Definition<TYPE> = prop
}
}
}
private class ListPropertyDelegateImpl<TYPE>(private val key: String?, private val sensitive: Boolean = false, private val addToProperties: (Configuration.Property.Definition<*>) -> Unit, private val construct: (String, Boolean) -> Configuration.Property.Definition.Required<TYPE>) : PropertyDelegate.Required<TYPE> {
private class ListPropertyDelegateImpl<TYPE>(private val key: String?, private val prefix: String?, private val sensitive: Boolean = false, private val addToProperties: (Configuration.Property.Definition<*>) -> Unit, private val construct: (String, Boolean) -> Configuration.Property.Definition.Required<TYPE>) : PropertyDelegate.Required<TYPE> {
override operator fun provideDelegate(thisRef: Any?, property: KProperty<*>): ReadOnlyProperty<Any?, Configuration.Property.Definition.Required<TYPE>> {
val prop = construct.invoke(key ?: property.name, sensitive).also(addToProperties)
val shortName = key ?: property.name
val prop = construct.invoke(prefix?.let { "$prefix.$shortName" } ?: shortName, sensitive).also(addToProperties)
return object : ReadOnlyProperty<Any?, Configuration.Property.Definition.Required<TYPE>> {
override fun getValue(thisRef: Any?, property: KProperty<*>): Configuration.Property.Definition.Required<TYPE> = prop
}
}
override fun optional(defaultValue: TYPE?): PropertyDelegate<TYPE?> = OptionalPropertyDelegateImpl(key, sensitive, addToProperties, { k, s -> construct.invoke(k, s).optional(defaultValue) })
override fun optional(): PropertyDelegate.Optional<TYPE> = OptionalPropertyDelegateImpl(key, prefix, sensitive, addToProperties, { k, s -> construct.invoke(k, s).optional() })
}

View File

@ -15,6 +15,10 @@ operator fun <TYPE> Config.get(property: Configuration.Property.Definition<TYPE>
inline fun <reified NESTED : Any> Configuration.Specification<*>.nested(specification: Configuration.Specification<NESTED>, key: String? = null, sensitive: Boolean = false): PropertyDelegate.Standard<NESTED> = nestedObject(schema = specification, key = key, sensitive = sensitive).map(ConfigObject::toConfig).mapValid { value -> specification.parse(value) }
fun <TYPE> Configuration.Property.Definition.Single<TYPE>.listOrEmpty(): Configuration.Property.Definition<List<TYPE>> = list().optional().withDefaultValue(emptyList())
fun <TYPE> PropertyDelegate.Single<TYPE>.listOrEmpty(): PropertyDelegate<List<TYPE>> = list().optional().withDefaultValue(emptyList())
@Suppress("UNCHECKED_CAST")
internal fun configObject(vararg entries: Pair<String, Any?>): ConfigObject {

View File

@ -5,18 +5,21 @@ import net.corda.common.configuration.parsing.internal.Configuration
import net.corda.common.configuration.parsing.internal.Valid
import net.corda.common.configuration.parsing.internal.valid
internal class VersionExtractor(versionKey: String, versionDefaultValue: Int?) : Configuration.Version.Extractor {
internal class VersionExtractor(versionPath: String, versionDefaultValue: Int) : Configuration.Version.Extractor {
private val spec = Spec(versionKey, versionDefaultValue)
private val containingPath = versionPath.split(".").let { if (it.size > 1) it.subList(0, it.size - 1) else null }
private val key = versionPath.split(".").last()
override fun parse(configuration: Config, options: Configuration.Validation.Options): Valid<Int?> {
private val spec = Spec(key, versionDefaultValue, containingPath?.joinToString("."))
override fun parse(configuration: Config, options: Configuration.Validation.Options): Valid<Int> {
return spec.parse(configuration)
}
private class Spec(versionKey: String, versionDefaultValue: Int?) : Configuration.Specification<Int?>("Version") {
private class Spec(key: String, versionDefaultValue: Int, prefix: String?) : Configuration.Specification<Int>("Version", prefix) {
private val version by int(key = versionKey).optional(versionDefaultValue)
private val version by int(key = key).optional().withDefaultValue(versionDefaultValue)
override fun parseValid(configuration: Config) = valid(version.valueIn(configuration))
}

View File

@ -95,7 +95,7 @@ class PropertyTest {
val configuration = configObject(key to null).toConfig()
val defaultValue = listOf(1L, 2L, 3L)
val property = Configuration.Property.Definition.long(key).list().optional(defaultValue)
val property = Configuration.Property.Definition.long(key).list().optional().withDefaultValue(defaultValue)
println(property)
assertThat(property.key).isEqualTo(key)
@ -173,7 +173,7 @@ class PropertyTest {
val configuration = configObject(key to null).toConfig()
val defaultValue = 23L
val property = Configuration.Property.Definition.long(key).optional(defaultValue)
val property = Configuration.Property.Definition.long(key).optional().withDefaultValue(defaultValue)
println(property)
assertThat(property.key).isEqualTo(key)

View File

@ -1,9 +1,7 @@
package net.corda.common.configuration.parsing.internal
import com.typesafe.config.Config
import net.corda.common.validation.internal.Validated.Companion.invalid
import net.corda.common.validation.internal.Validated.Companion.valid
import net.corda.common.validation.internal.Validator
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
@ -15,7 +13,7 @@ class PropertyValidationTest {
val key = "a.b.c"
val configuration = configObject().toConfig()
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.long(key)
val property = Configuration.Property.Definition.long(key)
assertThat(property.validate(configuration).errors).satisfies { errors ->
@ -34,7 +32,7 @@ class PropertyValidationTest {
val key = "a.b.c"
val configuration = configObject(key to null).toConfig()
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.long(key)
val property = Configuration.Property.Definition.long(key)
assertThat(property.validate(configuration).errors).satisfies { errors ->
@ -53,7 +51,7 @@ class PropertyValidationTest {
val key = "a.b.c"
val configuration = configObject().toConfig()
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.long(key).list()
val property = Configuration.Property.Definition.long(key).list()
assertThat(property.validate(configuration).errors).satisfies { errors ->
@ -72,7 +70,7 @@ class PropertyValidationTest {
val key = "a.b.c"
val configuration = configObject(key to null).toConfig()
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.long(key).list()
val property = Configuration.Property.Definition.long(key).list()
assertThat(property.validate(configuration).errors).satisfies { errors ->
@ -90,7 +88,7 @@ class PropertyValidationTest {
val key = "a.b.c"
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.long(key)
val property = Configuration.Property.Definition.long(key)
val configuration = configObject(key to false).toConfig()
@ -110,7 +108,7 @@ class PropertyValidationTest {
val key = "a.b.c"
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.long(key)
val property = Configuration.Property.Definition.long(key)
val configuration = configObject(key to 1.2).toConfig()
@ -130,7 +128,7 @@ class PropertyValidationTest {
val key = "a.b.c"
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.double(key)
val property = Configuration.Property.Definition.double(key)
val configuration = configObject(key to 1).toConfig()
@ -142,7 +140,7 @@ class PropertyValidationTest {
val key = "a.b.c"
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.long(key).list()
val property = Configuration.Property.Definition.long(key).list()
val configuration = configObject(key to listOf(false, true)).toConfig()
@ -162,7 +160,7 @@ class PropertyValidationTest {
val key = "a.b.c"
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.long(key)
val property = Configuration.Property.Definition.long(key)
val configuration = configObject(key to listOf(1, 2, 3)).toConfig()
@ -182,7 +180,7 @@ class PropertyValidationTest {
val key = "a.b.c"
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.long(key).list()
val property = Configuration.Property.Definition.long(key).list()
val configuration = configObject(key to 1).toConfig()
@ -205,7 +203,7 @@ class PropertyValidationTest {
val nestedKey = "d"
val nestedPropertySchema = Configuration.Schema.withProperties(Configuration.Property.Definition.long(nestedKey))
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.nestedObject(key, nestedPropertySchema)
val property = Configuration.Property.Definition.nestedObject(key, nestedPropertySchema)
val configuration = configObject(key to configObject(nestedKey to false)).toConfig()
@ -228,7 +226,7 @@ class PropertyValidationTest {
val nestedKey = "d"
val nestedPropertySchema = Configuration.Schema.withProperties(Configuration.Property.Definition.long(nestedKey))
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.nestedObject(key, nestedPropertySchema)
val property = Configuration.Property.Definition.nestedObject(key, nestedPropertySchema)
val configuration = configObject(key to configObject()).toConfig()
@ -251,7 +249,7 @@ class PropertyValidationTest {
val nestedKey = "d"
val nestedPropertySchema = Configuration.Schema.withProperties(Configuration.Property.Definition.long(nestedKey))
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.nestedObject(key, nestedPropertySchema)
val property = Configuration.Property.Definition.nestedObject(key, nestedPropertySchema)
val configuration = configObject(key to configObject(nestedKey to null)).toConfig()
@ -273,7 +271,7 @@ class PropertyValidationTest {
val nestedKey = "d"
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.nestedObject(key)
val property = Configuration.Property.Definition.nestedObject(key)
val configuration = configObject(key to configObject(nestedKey to false)).toConfig()
@ -285,7 +283,7 @@ class PropertyValidationTest {
val key = "a"
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.string(key).mapValid(::parseAddress)
val property = Configuration.Property.Definition.string(key).mapValid(::parseAddress)
val host = "localhost"
val port = 8080
@ -301,7 +299,7 @@ class PropertyValidationTest {
val key = "a.b.c"
val property: Validator<Config, Configuration.Validation.Error, Configuration.Validation.Options> = Configuration.Property.Definition.string(key).mapValid(::parseAddress)
val property = Configuration.Property.Definition.string(key).mapValid(::parseAddress)
val host = "localhost"
val port = 8080

View File

@ -39,7 +39,7 @@ class SpecificationTest {
val rpcSettings = RpcSettingsSpec.parse(configuration)
assertThat(rpcSettings.isValid).isTrue()
assertThat(rpcSettings.valueOrThrow()).satisfies { value ->
assertThat(rpcSettings.orThrow()).satisfies { value ->
assertThat(value.useSsl).isEqualTo(useSslValue)
assertThat(value.addresses).satisfies { addresses ->

View File

@ -9,8 +9,8 @@ import org.junit.Test
class VersionExtractorTest {
private val versionExtractor = Configuration.Version.Extractor.fromKey("configuration.metadata.version")
private val extractVersion: (Config) -> Valid<Int?> = { config -> versionExtractor.parse(config) }
private val versionExtractor = Configuration.Version.Extractor.fromPath("configuration.metadata.version")
private val extractVersion: (Config) -> Valid<Int> = { config -> versionExtractor.parse(config) }
@Test
fun version_header_extraction_present() {
@ -18,7 +18,7 @@ class VersionExtractorTest {
val versionValue = Configuration.Version.Extractor.DEFAULT_VERSION_VALUE + 1
val rawConfiguration = configObject("configuration" to configObject("metadata" to configObject("version" to versionValue), "node" to configObject("p2pAddress" to "localhost:8080"))).toConfig()
val version = extractVersion.invoke(rawConfiguration).valueOrThrow()
val version = extractVersion.invoke(rawConfiguration).orThrow()
assertThat(version).isEqualTo(versionValue)
}
@ -27,7 +27,7 @@ class VersionExtractorTest {
val rawConfiguration = configObject("configuration" to configObject("node" to configObject("p2pAddress" to "localhost:8080"))).toConfig()
val version = extractVersion.invoke(rawConfiguration).valueOrThrow()
val version = extractVersion.invoke(rawConfiguration).orThrow()
assertThat(version).isEqualTo(Configuration.Version.Extractor.DEFAULT_VERSION_VALUE)
}
@ -36,7 +36,7 @@ class VersionExtractorTest {
val rawConfiguration = configObject("configuration" to configObject("metadata" to configObject(), "node" to configObject("p2pAddress" to "localhost:8080"))).toConfig()
val version = extractVersion.invoke(rawConfiguration).valueOrThrow()
val version = extractVersion.invoke(rawConfiguration).orThrow()
assertThat(version).isEqualTo(Configuration.Version.Extractor.DEFAULT_VERSION_VALUE)
}
@ -46,7 +46,7 @@ class VersionExtractorTest {
val rawConfiguration = configObject("configuration" to configObject("metadata" to configObject("version" to null), "node" to configObject("p2pAddress" to "localhost:8080"))).toConfig()
val version = extractVersion.invoke(rawConfiguration).valueOrThrow()
val version = extractVersion.invoke(rawConfiguration).orThrow()
assertThat(version).isEqualTo(Configuration.Version.Extractor.DEFAULT_VERSION_VALUE)
}
@ -56,7 +56,7 @@ class VersionExtractorTest {
val rawConfiguration = configObject().toConfig()
val version = extractVersion.invoke(rawConfiguration).valueOrThrow()
val version = extractVersion.invoke(rawConfiguration).orThrow()
assertThat(version).isEqualTo(Configuration.Version.Extractor.DEFAULT_VERSION_VALUE)
}

View File

@ -12,7 +12,7 @@ class VersionedParsingExampleTest {
@Test
fun correct_parsing_function_is_used_for_present_version() {
val versionParser = Configuration.Version.Extractor.fromKey("configuration.metadata.version", null)
val versionParser = Configuration.Version.Extractor.fromPath("configuration.metadata.version")
val extractVersion: (Config) -> Valid<Int> = { config -> versionParser.parseRequired(config) }
val parseConfiguration = VersionedSpecificationRegistry.mapping(extractVersion, 1 to RpcSettingsSpec.V1, 2 to RpcSettingsSpec.V2)
@ -35,7 +35,7 @@ class VersionedParsingExampleTest {
fun default_value_is_used_for_absent_version() {
val defaultVersion = 2
val versionParser = Configuration.Version.Extractor.fromKey("configuration.metadata.version", defaultVersion)
val versionParser = Configuration.Version.Extractor.fromPath("configuration.metadata.version", defaultVersion)
val extractVersion: (Config) -> Valid<Int> = { config -> versionParser.parseRequired(config) }
val parseConfiguration = VersionedSpecificationRegistry.mapping(extractVersion, 1 to RpcSettingsSpec.V1, 2 to RpcSettingsSpec.V2)
@ -52,7 +52,7 @@ class VersionedParsingExampleTest {
private fun assertResult(result: Valid<RpcSettings>, principalAddressValue: Address, adminAddressValue: Address) {
assertThat(result.isValid).isTrue()
assertThat(result.valueOrThrow()).satisfies { value ->
assertThat(result.orThrow()).satisfies { value ->
assertThat(value.principal).isEqualTo(principalAddressValue)
assertThat(value.admin).isEqualTo(adminAddressValue)