Hi all, my name is Hubert A. Klein Ikkink. Not a very common name, right? To make things easier I just picked the first letters of my firstname and surname and came up with haki. So there you have it, now I am also known as Mr. Haki or mrhaki for short. You can read more blog postings at www.mrhaki.com. I am a passionate Groovy and Java developer based in Tilburg, The Netherlands. My goal is to write clean, elegant, user-centered and high quality software. You can find me on Google+ and Twitter. Hubert is a DZone MVB and is not an employee of DZone and has posted 160 posts at DZone. You can read more from them at their website. View Full User Profile

Groovy Goodness: Create Our Own Script Class

11.19.2011
| 7044 views |
  • submit to reddit

Groovy is a great language to write DSL implementations. The Groovy syntax allows for example to leave out parenthesis or semi colons, which results in better readable DSL (which is actually Groovy code).

To run a DSL script we can use the GroovyShell class and evaluate the script. By default the script is evaluated with an instance of groovy.lang.Script class. But we can extends this Script class and write our DSL allowed methods, which can then be used by the DSL script. We pass our own Script class to the GroovyShell with an CompilerConfiguration object. The CompilerConfiguration allows us to set a new base script class to be used.

The following sample is a simple DSL to change the state of a Car object. Notice we implicitly access the Car object that is passed to the GroovyShell via a binding. The custom CarScript class can access the car object via the binding and change it's state.

import org.codehaus.groovy.control.CompilerConfiguration

// Simple Car class to save state and distance.
class Car {
    String state
    Long distance = 0
}

// Custom Script with methods that change the Car's state.
// The Car object is passed via the binding.
abstract class CarScript extends Script {
    def start() {
        this.binding.car.state = 'started'
    }

    def stop() {
        this.binding.car.state = 'stopped'
    }

    def drive(distance) {
        this.binding.car.distance += distance
    }
}


// Use custom CarScript.
def compilerConfiguration = new CompilerConfiguration()
compilerConfiguration.scriptBaseClass = CarScript.class.name

// Define Car object here, so we can use it in assertions later on.
def car = new Car()
// Add to script binding (CarScript references this.binding.car).
def binding = new Binding(car: car)

// Configure the GroovyShell.
def shell = new GroovyShell(this.class.classLoader, binding, compilerConfiguration)

// Simple DSL to start, drive and stop the car.
// The methods are defined in the CarScript class.
def carDsl = '''
start()
drive 20
stop()
'''

// Run DSL script.
shell.evaluate carDsl

// Checks to see that Car object has changed.
assert car.distance == 20
assert car.state == 'stopped'

 

From http://mrhaki.blogspot.com/2011/11/groovy-goodness-create-our-own-script.html

Published at DZone with permission of Hubert Klein Ikkink, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Amara Amjad replied on Sun, 2012/03/25 - 1:16am

Although maybe not entirely appropriate in this specific example, but in general you can also specify the script base class on the command line by using a system property:

groovy -Dgroovy.script.base=CarScript mytest

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.