I am writing a small Groovy DSL for letting end-users define configuration files. The idea is that I load those files in a Java environment, set some values and execute them. Here a small example from the DSL so far (the Gradle-ish style is on purpose):
model {
file "some/path/here"
conformsTo "some/other/path/here"
}
model {
...
}
If I save above code to a file (example.groovy), I can integrate it with Java through the GroovyShell:
Binding binding = new Binding();
GroovyShell shell = new GroovyShell(binding);
Object value = shell.evaluate(...);
The tricky part is setting the "root" object. I know I can use Bindings to set in and out variables. However, I want that the "model" blocks in the DSL are mapped to a method call, i.e. I want to specify a "this" equivalent for the whole script. Anything I write in the DSL should be in scope of this "root" object, e.g.
// model is a method of the root object
model {
file "some/path/here"
conformsTo someValue // if someValue is not defined inside the script, I want it to be considered as a property of the root object
}
I found this excellent article about what I want to achieve, but since it is from 2008, I thought there may be better options in newer Groovy versions. I just don't know what to look for. Can anyone point me in the right direction?
If this is plain Groovy (not Gradle), then groovy.util.DelegatingScript is what you are looking for. Check its Javadoc for details.
DelegatingScript is a convenient basis for loading a custom-defined DSL as a Script, then execute it. The following sample code illustrates how to do it:
class MyDSL { public void foo(int x, int y, Closure z) { ... } public void setBar(String a) { ... } } CompilerConfiguration cc = new CompilerConfiguration(); cc.setScriptBaseClass(DelegatingScript.class); GroovyShell sh = new GroovyShell(cl,new Binding(),cc); DelegatingScript script = (DelegatingScript)sh.parse(new File("my.dsl")) script.setDelegate(new MyDSL()); script.run();my.dsl can look like this:
foo(1,2) { .... } bar = ...;
There is simple solution in Groovy to keep the configuration in properties, it's a ConfigSlurper. Have a look into ConfigSlurper
sample {
foo = "default_foo"
bar = "default_bar"
}
environments {
development {
sample {
foo = "dev_foo"
}
}
test {
sample {
bar = "test_bar"
}
}
}
def config = new ConfigSlurper("development").parse(new File('Sample.groovy').toURL())
assert config.sample.foo == "dev_foo"
assert config.sample.bar == "default_bar"
config = new ConfigSlurper("test").parse(new File('Sample.groovy').toURL())
assert config.sample.foo == "default_foo"
assert config.sample.bar == "test_bar"
Hope this is what you are looking for.
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