diff --git a/cfg4k-bytebuddy/src/main/kotlin/com/jdiazcano/cfg4k/bytebuddy/ByteBuddyConfigProvider.kt b/cfg4k-bytebuddy/src/main/kotlin/com/jdiazcano/cfg4k/bytebuddy/ByteBuddyConfigProvider.kt index 92028be..216d75a 100644 --- a/cfg4k-bytebuddy/src/main/kotlin/com/jdiazcano/cfg4k/bytebuddy/ByteBuddyConfigProvider.kt +++ b/cfg4k-bytebuddy/src/main/kotlin/com/jdiazcano/cfg4k/bytebuddy/ByteBuddyConfigProvider.kt @@ -144,7 +144,7 @@ class ConfigurationHandler { val targetType = TargetType(returnType) val rawType = targetType.rawTargetType() val collection = createCollection(rawType) - toMutableCollection(configObject, returnType, collection, name, provider, prefix) + toMutableCollection(configObject, targetType, collection, name, provider, prefix) returning = collection } else if (configObject.isString()) { val targetType = TargetType(returnType) diff --git a/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/binders/BindingInvocationHandler.kt b/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/binders/BindingInvocationHandler.kt index 4286b22..0cae285 100644 --- a/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/binders/BindingInvocationHandler.kt +++ b/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/binders/BindingInvocationHandler.kt @@ -67,15 +67,13 @@ class BindingInvocationHandler( } } } else { + val targetType = TargetType(type) + val rawType = targetType.rawTargetType() if (configObject.isList()) { - val targetType = TargetType(type) - val rawType = targetType.rawTargetType() val collection = createCollection(rawType) - toMutableCollection(configObject, type, collection, name, provider, prefix) + toMutableCollection(configObject, targetType, collection, name, provider, prefix) return collection } else if (configObject.isString()) { - val targetType = TargetType(type) - val rawType = targetType.rawTargetType() val superType = targetType.getParameterizedClassArguments().firstOrNull() val classType = superType ?: rawType return classType.findParser().parse(configObject, classType, superType?.findParser()) @@ -104,14 +102,12 @@ fun createCollection(rawType: Class<*>): MutableCollection { } } -fun toMutableCollection(configObject: ConfigObject, type: Type, list: MutableCollection, name: String, provider: ConfigProvider, prefix: String) { +fun toMutableCollection(configObject: ConfigObject, targetType: TargetType, list: MutableCollection, name: String, provider: ConfigProvider, prefix: String) { configObject.asList().forEachIndexed { index, innerObject -> if (innerObject.isObject()) { - val targetType = TargetType(type) val superType = targetType.getParameterizedClassArguments().firstOrNull() list.add(provider.bind(concatPrefix(prefix, "$name[$index]"), superType as Class)) } else if (innerObject.isString()) { - val targetType = TargetType(type) val rawType = targetType.rawTargetType() val superType = targetType.getParameterizedClassArguments().firstOrNull() val classType = superType ?: rawType @@ -121,7 +117,7 @@ fun toMutableCollection(configObject: ConfigObject, type: Type, list: MutableCol } fun KClass<*>.getDefaultMethod(methodName: String): Method? { - return Class.forName(jvmName + "\$DefaultImpls").methods.firstOrNull { it.name == methodName } + return Class.forName("$jvmName\$DefaultImpls").methods.firstOrNull { it.name == methodName } } fun KClass<*>.isMethodNullable(method: Method, propertyName: String = ""): Boolean { diff --git a/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/core/ConfigObject.kt b/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/core/ConfigObject.kt index 16d1398..6dcd153 100644 --- a/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/core/ConfigObject.kt +++ b/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/core/ConfigObject.kt @@ -12,10 +12,13 @@ interface ConfigObject { fun child(key: String): ConfigObject? { val (number, cleanKey) = findNumbers(key) - return if (number == null) { - asObject()[cleanKey] - } else { - asObject()[cleanKey]?.asList()?.get(number) + return when { + // We're in a normal object + number == null -> asObject()[cleanKey] + // We're in a list that is ROOT + cleanKey.isEmpty() -> asList()[number] + // When we are in a list that is inside our object + else -> asObject()[cleanKey]?.asList()?.get(number) } } diff --git a/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/loaders/DefaultConfigLoader.kt b/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/loaders/DefaultConfigLoader.kt index 6005e01..c729a04 100644 --- a/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/loaders/DefaultConfigLoader.kt +++ b/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/loaders/DefaultConfigLoader.kt @@ -42,12 +42,12 @@ open class DefaultConfigLoader(protected var root: ConfigObject = "".toConfig()) } -internal val numberRegex = "([^\\[]+)(?:\\[(\\d+)])".toRegex() +internal val numberRegex = "([^\\[]+)?(?:\\[(\\d+)])".toRegex() internal fun findNumbers(key: String): Pair { val result = numberRegex.find(key) return if (result != null) { - result.groups[2]?.value?.toInt() to result.groups[1]?.value!! + result.groups[2]?.value?.toInt() to (result.groups[1]?.value ?: "") } else { null to key } diff --git a/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/providers/DefaultConfigProvider.kt b/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/providers/DefaultConfigProvider.kt index ee1b967..1712984 100644 --- a/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/providers/DefaultConfigProvider.kt +++ b/cfg4k-core/src/main/kotlin/com/jdiazcano/cfg4k/providers/DefaultConfigProvider.kt @@ -71,10 +71,8 @@ open class DefaultConfigProvider( val classType = superType ?: rawType return rawType.findParser().parse(value, classType, superType?.findParser()) as T } else if (value.isList()) { - val superType = targetType.getParameterizedClassArguments().firstOrNull() - val classType = superType ?: rawType val collection = createCollection(rawType) - toMutableCollection(value, classType, collection, name, this, name) + toMutableCollection(value, targetType, collection, name, this, name) return collection as T } throw ParserClassNotFound("Parser for class $type was not found") diff --git a/cfg4k-s3/build.gradle b/cfg4k-s3/build.gradle index 2e3a284..36dc1db 100644 --- a/cfg4k-s3/build.gradle +++ b/cfg4k-s3/build.gradle @@ -5,6 +5,7 @@ dependencies { compile libraries.jetbrains.kotlin.stdlib compile libraries.aws.s3 + testCompile project(":cfg4k-json") testCompile libraries.jetbrains.spek.api testCompile libraries.junitrunner testCompile libraries.expekt diff --git a/cfg4k-s3/src/main/kotlin/com/jdiazcano/cfg4k/s3/S3ConfigSource.kt b/cfg4k-s3/src/main/kotlin/com/jdiazcano/cfg4k/s3/S3ConfigSource.kt index 41fc3eb..83bed0a 100644 --- a/cfg4k-s3/src/main/kotlin/com/jdiazcano/cfg4k/s3/S3ConfigSource.kt +++ b/cfg4k-s3/src/main/kotlin/com/jdiazcano/cfg4k/s3/S3ConfigSource.kt @@ -1,6 +1,6 @@ package com.jdiazcano.cfg4k.s3 -import com.amazonaws.services.s3.AmazonS3Client +import com.amazonaws.services.s3.AmazonS3 import com.jdiazcano.cfg4k.sources.ConfigSource import java.io.InputStream @@ -10,7 +10,7 @@ import java.io.InputStream * @since 0.8.6 */ class S3ConfigSource( - private val client: AmazonS3Client, + private val client: AmazonS3, private val bucket: String, private val objectName: String ) : ConfigSource { diff --git a/cfg4k-s3/src/test/kotlin/com/jdiazcano/cfg4k/s3/S3ConfigSourceTest.kt b/cfg4k-s3/src/test/kotlin/com/jdiazcano/cfg4k/s3/S3ConfigSourceTest.kt new file mode 100644 index 0000000..8c8abfc --- /dev/null +++ b/cfg4k-s3/src/test/kotlin/com/jdiazcano/cfg4k/s3/S3ConfigSourceTest.kt @@ -0,0 +1,32 @@ +package com.jdiazcano.cfg4k.s3 + +import com.amazonaws.regions.Regions +import com.amazonaws.services.s3.AmazonS3ClientBuilder +import com.jdiazcano.cfg4k.json.JsonConfigLoader +import com.jdiazcano.cfg4k.providers.DefaultConfigProvider +import com.jdiazcano.cfg4k.providers.cache +import com.jdiazcano.cfg4k.providers.get +import com.winterbe.expekt.should +import org.jetbrains.spek.api.Spek +import org.jetbrains.spek.api.dsl.describe + +class S3ConfigSourceTest : Spek({ + describe("a config source that can fetch data") { + val client = AmazonS3ClientBuilder.standard().withRegion(Regions.US_EAST_1).build() + val source = S3ConfigSource(client, "mtln-public-data", "Samples/airports.json") + val loader = JsonConfigLoader(source) + val provider = DefaultConfigProvider(loader).cache() + val airports = provider.get>() + airports.should.not.be.empty + } +}) + +private interface Airport { + val iata: String + val airport: String + val city: String + val state: String + val country: String + val lat: Double + val long: Double +} \ No newline at end of file