I have a DSL where, if present, a closure called before
will be called before every command.
In my setup I have 3 files: The script itself - Script
, a ScriptBase
, that is 'attached' to the script via a CompilerConfiguration
, and a Handler
.
In the script I may or may not have a closure called before
.
before = {
//Do stuff.
}
Notice the lack of a type declaration, or def
. If I understand Groovy correctly, this means that before
is a in the binding, and accessible from outside code when evaluated with GroovyShell.evaluate()
.
In the ScriptBase I do the following:
class ProductSpecificationBase extends Script {
def before = null
}
This script base may or may not be overridden later on.
Then, in the Handler
, I'm doing a check for whether a before
closure is defined in the script:
def config = new CompilerConfiguration()
config.setScriptBaseClass(ScriptBase.class.name)
def shell = GroovyShell()
evaluatedScript = shell.evaluate(new File(thePathToScript))
if (evaluatedScript.before) {
theEvaluationOfMyScript.before()
}
The code works as expected if the script does contain a before
closure, but if it doesn't it returns a MissingPropertyException
. I've had a look at what this means, and it seems that my before
in the ScriptBase
isn't considered a property, and all the examples of using these ScriptBase
s I've found on the internet give examples of using methods. This is not feasible for my use case I'm afraid. How can I ensure that the closure in the ScriptBase
is considered a property instead of a field(as I am assuming it is now).
To be paraphrase: I would like my code to not execute the if
block if the script does not contain a before
closure as well as not having been overridden in an extension of the ScriptBase
. However, I would like the evaluation of evaluatedScript.before
to be false
as it is an empty/null Closure (i.e. it went all the way up to ScriptBase
, and found the null closure)
I like to avoid a try/catch approach if possible.
in your example you would basically call the getter for the
before
property. To check, if there is a method with the name (and params) check withrespondsTo
. To see, if there is a property at all with that name usehasProperty
(Thanks @dmahapatro for pointing this out)