I would like to read the following configuration from a HOCON (Typesafe Config) file into Kotlin.
tablename: {
columns: [
{ item: { type: integer, key: true, null: false } }
{ desc: { type: varchar, length: 64 } }
{ quantity: { type: integer, null: false } }
{ price: { type: decimal, precision: 14, scale: 3 } }
]
}
In fact I would like to extract the key column(s). I have tried the following so far.
val metadata = ConfigFactory.parseFile(metafile)
val keys = metadata.getObjectList("${tablename.toLowerCase()}.columns")
.filter { it.unwrapped().values.first().get("key") == true }
But it fails with the following error.
Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
@kotlin.internal.InlineOnly public operator inline fun <@kotlin.internal.OnlyInputTypes K, V> kotlin.collections.Map<out kotlin.String, ???>.get(key: kotlin.String): ??? defined in kotlin.collections
It is clear that Kotlin is not able to understand the data type of the "value" field in the Map. How do I declare it or let Kotlin know?
Also not that there are different types and optional keys in this Map.
PS: I know that there are couple of wrappers available for Kotlin such as Konfig and Klutter. I was hoping that if this is easy to write I could avoid another library.
UPDATE 1:
I have tried the following.
it.unwrapped().values.first().get<String, Boolean>("key")
to get the following compiler error.
Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
@kotlin.internal.InlineOnly public operator inline fun <@kotlin.internal.OnlyInputTypes K, V> kotlin.collections.Map<out kotlin.String, kotlin.Boolean>.get(key: kotlin.String): kotlin.Boolean? defined in kotlin.collections
And this
it.unwrapped().values.first().get<String, Boolean?>("key")
with output
Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
@kotlin.internal.InlineOnly public operator inline fun <@kotlin.internal.OnlyInputTypes K, V> kotlin.collections.Map<out kotlin.String, kotlin.Boolean?>.get(key: kotlin.String): kotlin.Boolean? defined in kotlin.collections
UPDATE 2:
Looking at the way it is handled elsewhere, I guess I probably need to use reflection. Trying it out with my limited exposure. No luck so far.
Consider your code, deconstructed below:
val keys = metadata.getObjectList("tablename.columns")
.filter {
val item:ConfigObject = it
val unwrapped:Map<String,Any?> = item.unwrapped()
val values:Collection<Any?> = unwrapped.values
val firstValue:Any? = values.first()
firstValue.get("key") == true // does not compile
}
From the above the problem should be obvious. You need to aid the compiler with the information that firstValue
holds a Map
like so:
val firstValueMap = firstValue as Map<String,Any?>
firstValueMap["key"] == true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With