I am experimenting with using the ConfigSlurper to parse Groovy files that will be used as configuration files for a Java program.
I want to support hierarchical configurations with base properties that can be overridden if needed. I figured closures would be a good way to represent this, but I've run into a small problem.
I can get base keys to be propagated to child configurations by left-shifting the base closure onto the child closure:
base {
baseKey = "All closures that compose from this closure will have this key"
}
config1 {
config1only = "value"
}
config1 << base
config2 {
config2only = "another value"
}
config2 << base
When I pretty print the ConfigObject, I get what I was hoping:
base.baseKey='All closures that compose from this closure will have this key'
config1 {
config1only='value'
baseKey='All closures that compose from this closure will have this key'
}
config2 {
config2only='another value'
baseKey='All closures that compose from this closure will have this key'
}
Perfect! However, when I try to override a base key in one of the config closures, the base key from the base closure seems to be taking precedence, which isn't what I was expecting. Here is the source:
base {
baseKey = "All closures that compose from this closure will have this key"
overiddenKey = "base"
}
config1 {
config1only = "value"
overiddenKey = "override1"
}
config1 << base
config2 {
config2only = "another value"
overiddenKey = "override2"
}
config2 << base
Here is the pretty printed ConfigObject:
base {
baseKey='All closures that compose from this closure will have this key'
overiddenKey='base'
}
config1 {
config1only='value'
overiddenKey='base'
baseKey='All closures that compose from this closure will have this key'
}
config2 {
config2only='another value'
overiddenKey='base'
baseKey='All closures that compose from this closure will have this key'
}
I tried changing to the shift to a right shift, but I kept getting an error:
Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: groovy.util.ConfigObject.leftShift() is applicable for argument types: (script15162997138121381677545$_run_closure1) values: [script15162997138121381677545$_run_closure1@3d246ea3]
Possible solutions: leftShift(java.util.Map), leftShift(java.util.Map$Entry)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:54)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at script15162997138121381677545.run(script15162997138121381677545.groovy:18)
Now this is all probably due to my limited understanding of how groovy closures work, so any help would be appreciated.
Update:
So It looks like I've managed to get to what I'm after by using base.clone():
base {
baseKey = "All closures that compose from this closure will have this key"
overiddenKey = "base"
}
config1 = base.clone()
config1 {
config1only = "value"
}
config2 = base.clone()
config2 {
config2only = "another value"
overiddenKey = "override2"
}
Which produces exactly what I was expecting:
base {
baseKey='All closures that compose from this closure will have this key'
overiddenKey='base'
}
config1 {
baseKey='All closures that compose from this closure will have this key'
overiddenKey='base'
config1only='value'
}
config2 {
baseKey='All closures that compose from this closure will have this key'
overiddenKey='override2'
config2only='another value'
}
But the whole configN = base.clone() before the configN definition seems a little clunky. Is there a way I could clean that up a bit? Or is maybe using groovy not the best option?
Is this what you want?
Input:
base {
baseKey = "All closures that compose from this closure will have this key"
overiddenKey = "base"
}
config1 << base
config1 {
config1only = "value"
overiddenKey = "override1"
}
config2 << base
config2 {
config2only = "another value"
overiddenKey = "override2"
}
Output:
base {
baseKey='All closures that compose from this closure will have this key'
overiddenKey='base'
}
config1 {
baseKey='All closures that compose from this closure will have this key'
overiddenKey='override1'
config1only='value'
}
config2 {
baseKey='All closures that compose from this closure will have this key'
overiddenKey='override2'
config2only='another value'
}
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