Jim Driscoll's Blog

Notes on Technology and the Web

Groovy Bindings – or adding keywords to your DSL

leave a comment »

Having now covered executing Groovy scripts in your Java programs, it’s time to make our first DSL modification.   One thing that would be very handy would be to add keywords to our new language.  We can do that by passing a custom Binding to our Groovy Script.

The Binding in a Groovy Script offers a fairly interesting feature – it’s an outermost scoping which doesn’t require a variable definition.  So, in a Groovy Script, I can say:

name = 'Jim'
println "hello $name"

 

In this code, I’m not actually declaring a local variable called name – instead, I’m creating a slot in the Groovy Binding with a name of name, and a value of a String object (‘Jim’).  Under the hood, the default Binding that Groovy gives us keeps a map – “name” will be the key, and “Jim” will be the value.  Since this is effectively an outermost scope, you can shadow the Binding values with local values as well – more on that later.

We can use this Binding in our code to pass values into and out of the script in a way that’s hopefully fairly easy for an enduser to understand.   You can use this facility to provide:

  • Constant values (e.g., the name of the current user, provided as a String)
  • Read only variables  (e.g., the current date and time, provided as a String, or some other object)
  • Default values for variables (e.g., The name of the application, as a String, overridable at runtime)

Creating a Binding is pretty straightforward – just extend the existing Binding class, overriding the setVariable and getVariable methods.

public class MyBinding extends Binding {
            
    public Object  getVariable(String name) {
        if ("name".equals(name)) {
            return "Jim";
        } else if ("date".equals(name)) {
            return new Date();
        }
        return super.getVariable(name);
    }
    public void setVariable(String name, Object value) {
        if ("date".equals(name) || "name".equals(name)) {
            throw new RuntimeException("variable "+name+" is read only");
        }
        super.setVariable(name, value);
    }
}

For this example, we’re creating two read only Binding variables – “name”, a constant String value equal to my name, and “date”, a variable value equal to the current date, returned as a Date object.   When the variables are used in a access context, getVariable is called, and we return the results we want the user to see.  When the variables are used in a modify context, we throw an exception if it’s one of the protected values.  Otherwise, we fall through to the underlying Binding class, which you’ll recall I mentioned just uses an underlying Map.  To use this new Binding, set it with the setBinding method of Script.  Then, the variables are accessible from the script.  Like so:

String runMe =
     "println 'hello '+ name \n"+
     "println 'it is now: ' +date";
GroovyShell shell = new GroovyShell();
Script script = shell.parse(runMe);
script.setBinding(new MyBinding());
script.run();

To recap, the script that’s run looks like this:

println 'hello ' + name
println 'it is now: ' + date

 

The output of this when run:

hello Jim
it is now: Sat Mar 17 11:19:27 PDT 2012

 

This is a pretty powerful technique, and I’ve only scratched the surface.  We’ll revisit more about this in later posts.

About these ads

Written by Jim Driscoll

April 14, 2012 at 12:40 PM

Posted in DSL, Groovy

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 411 other followers

%d bloggers like this: