Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending closure with another closure

Tags:

groovy

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?

like image 716
wheeler Avatar asked May 29 '26 02:05

wheeler


1 Answers

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'
}
like image 166
Jeff Scott Brown Avatar answered May 31 '26 15:05

Jeff Scott Brown



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!