Reputation: 92036
I want to resolve one Config
object, say config1
with other, say config2
.
The only public API that allows something of the sort is config1.withFallback(config2).resolve()
. However this adds entries from config2
to config1
which is not something we want.
On some investigation, we found a non-public class named ResolveContext
which provides a method for that. So we are making use of that using reflection. Our current code:
object ConfigImplicits {
implicit class RichConfig(val config: Config) extends AnyVal {
def resolveWith(source: Config): Config = {
val resolver = resolveContext.getDeclaredMethod(
"resolve",
abstractConfigValue,
abstractConfigObject,
configResolveOptions
)
resolver.setAccessible(true)
resolver.invoke(
null,
config.underlyingAbstractConfigObject,
source.underlyingAbstractConfigObject,
ConfigResolveOptions.defaults
).asInstanceOf[ConfigObject].toConfig
}
def underlyingAbstractConfigObject = {
val f = simpleConfig.getDeclaredField("object")
f.setAccessible(true)
f.get(config)
}
}
val resolveContext = Class forName "com.typesafe.config.impl.ResolveContext"
val abstractConfigValue = Class forName "com.typesafe.config.impl.AbstractConfigValue"
val abstractConfigObject = Class forName "com.typesafe.config.impl.AbstractConfigObject"
val configResolveOptions = classOf[ConfigResolveOptions]
val simpleConfig = Class forName "com.typesafe.config.impl.SimpleConfig"
}
We realize that relying on non-public innards might not be a good idea. So:
Upvotes: 2
Views: 1515
Reputation: 8467
There is not AFAIK a public method. A less-fragile workaround instead of relying on private API might be to first resolve with your source object in there as a fallback, then iterate over the keys in the source object you resolved from and just remove those unwanted keys from the target object.
I can't think of a reason not to add a Config.resolveWith(), though I wonder if there was a reason since I do remember considering it. Maybe I just figured nobody would use it.
If you do a pull request, be sure to include tests and docs. I think the pull request is reasonable, assuming it turns out to be very little code (as I would expect). The current master branch is open for API additions, to appear in an eventual 1.2 release.
Upvotes: 1