Search

Dark theme | Light theme

September 30, 2009

Groovy Goodness: Newify to Create New Instances

The @Newify transformation annotation allows other ways to create a new instance of a class. We can use a new() method on the class or even omit the whole new keyword. The syntax is copied from other languages like Ruby and Python. If we use the @Newify annotation we get a slightly more readable piece of code (in some situations). We can use parameters in the annotation to denote all those classes we want to be instantiated with the new() method or without the new keyword.

class Author {
    String name
    List books
}
class Book { 
    String title 
}

def createKing() {
    new Author(name: 'Stephen King', books: [
        new Book(title: 'Carrie'),
        new Book(title: 'The Shining'),
        new Book(title: 'It')
    ])
}

assert 3 == createKing().books.size()
assert 'Stephen King' == createKing().name
assert 'Carrie' == createKing().books.getAt(0).title

@Newify 
def createKingRuby() {
    Author.new(name: 'Stephen King', books: [
        Book.new(title: 'Carrie'),
        Book.new(title: 'The Shining'),
        Book.new(title: 'It')
    ])
}

assert 3 == createKingRuby().books.size()
assert 'Stephen King' == createKingRuby().name
assert 'Carrie, The Shining, It' == createKingRuby().books.title.join(', ')

@Newify([Author, Book]) 
def createKingPython() {
    Author(name: 'Stephen King', books: [
        Book(title: 'Carrie'),
        Book(title: 'The Shining'),
        Book(title: 'It')
    ])
}

assert 3 == createKingPython().books.size()
assert 'Stephen King' == createKingPython().name
assert 'It' == createKingPython().books.title.find { it == 'It' }

September 29, 2009

Groovy Goodness: Use Categories to Add Functionality to Classes

Categories allow us to add extra functionality to classes, even those classes we didn't develop ourselves. A Category class contain static methods. The first argument of the method determines the type the method can be applied to.

We can also use the @Category transformation annotation to make a class into a Category. The class doesn't have to define static methods anymore, but we can use instance methods. The parameter of the @Category annotation defines for which class the Category is.

The Category can be applied to a specific code block with the use keyword. Only within the code block the rules of the Category are applied.

class Speak {
    static String shout(String text) {  // Method argument is String, so we can add shout() to String object.
        text.toUpperCase() + '!'
    }
    
    static String whisper(String text, boolean veryQuiet = false) {
        "${veryQuiet ? 'sssssssh' : 'sssh'}.. $text"
    }
    
    static String army(String text) {
        "$text. Sir, yes sir!"
    }
}

use (Speak) {
    assert 'PAY ATTENTION!' == "Pay attention".shout()
    assert 'sssh.. Be vewy, vewy, quiet.' == "Be vewy, vewy, quiet.".whisper()
    assert 'sssssssh.. Be vewy, vewy, quiet.' == "Be vewy, vewy, quiet.".whisper(true)
    assert 'Groovy rocks. Sir, yes sir!' == "Groovy rocks".army()
}

// Or we can use the @Category annotation.
@Category(String) 
class StreetTalk {
    String hiphop() {
        "Yo, yo, here we go. ${this}"
    }
}

use(StreetTalk) {
    assert 'Yo, yo, here we go. Groovy is fun!' == 'Groovy is fun!'.hiphop()
}

// We can use static methods from other Java classes.
use (org.apache.commons.codec.digest.DigestUtils) {
    assert '900150983cd24fb0d6963f7d28e17f72' == 'abc'.md5Hex()
}

September 28, 2009

Groovy Goodness: Building Object Graphs

With Groovy we can build a graph of objects just like with Java, but we can also use the ObjectGraphBuilder. With the builder we can construct a graph of objects that follow the Java Beans rules. The builder follows some standard rules to determine parent/child relations and use of classes. We can override this default behaviour by adding specific resolver classes to the builder object.

class School {
    String name
    List<Course> courses = []
}

class Course {
    String name
    Teacher teacher
    List<Student> students = []
}

class Teacher { String name }

class Student { String name }

def builder = new ObjectGraphBuilder(classLoader: getClass().classLoader) // Need classLoader when in Groovy console.
def firstSchool = builder.school(name: 'First School') {
    course(name: 'Math') {
        teacher(name: 'Matt') 
        student(name: 'Mary', id: 'Mary')  // id attribute allows us to reference it later in the builder.
        student(name: 'John', id: 'John')
        student(name: 'Rose', id: 'Rose')
    }
    course(name: 'English') {
        teacher(name: 'Emily', id: 'Emily')
        student(refId: 'Mary')  // refId refers to id attribute we set earlier.
        student(name: 'Alex')
        student(refId: 'Rose')
    }
    course(name: 'Java') {
        teacher(refId: 'Emily')
        student(name: 'mrhaki')
        student(refId: 'John')
        student(refId: 'Mary')
    }    
}

assert 'First School' == firstSchool.name
assert 3 == firstSchool.courses.size()
assert 'Math' == firstSchool.courses[0].name
assert 'Matt' == firstSchool.courses[0].teacher.name
assert 3 == firstSchool.courses[0].students.size()
assert ['English', 'Java'] == firstSchool.courses.findAll{ it.teacher.name == 'Emily' }.name
assert 'mrhaki' == firstSchool.courses[2].students.find { it.name == 'mrhaki' }.name
assert 'Mary' == firstSchool.courses.find{ it.name == 'Java' }.students.find{ it.name == 'Mary' }.name

September 27, 2009

Groovy Goodness: Observable Map and List

Groovy provides the ObservableMap and ObservableList classes. These classes send out PropertyChangeEvent objects when we add, remove or change the contents of the map or list. For several actions we get different event types and we can use a PropertyChangeListener object to subscribe to these events. For example if we add an element we can subscribe to the property change event and get an PropertyAddedEvent.

import java.beans.*

def event 
// Listener will assign event to global event variable.
def listener = { 
    event = it
} as PropertyChangeListener

/* ObservableList */
def list = ['Groovy', 'rocks', 'the world', true] as ObservableList
list.addPropertyChangeListener(listener)

list << 'More text'
assert event instanceof ObservableList.ElementAddedEvent 
assert 4 == event.index
assert 'More text' == event.newValue

list.remove(3)
assert event instanceof ObservableList.ElementRemovedEvent
assert 3 == event.index

list[0] = 'Grails'
assert event instanceof ObservableList.ElementUpdatedEvent
assert 0 == event.index
assert 'Groovy' == event.oldValue
assert 'Grails' == event.newValue

list.addAll([42, 101])
assert event instanceof ObservableList.MultiElementAddedEvent
assert [42, 101] == event.values

list.removeAll([true, 'More text', 42, 101])
assert event instanceof ObservableList.MultiElementRemovedEvent
assert 3 == list.size()

list.clear()
assert event instanceof ObservableList.ElementClearedEvent
assert ['Grails', 'rocks', 'the world'] == event.values

event = null

// We can define a closure as a filter. The closure is
// executed for each element and if it returns true,
// the property change event is fired.
def strict = new ObservableList({ it.size() > 2 })
strict.addPropertyChangeListener(listener)
strict.addAll(['a', 'ab', 'abc', 'abcd'])
assert ['abc', 'abcd'] == event.values

/* ObservableMap */
event = null

// Extra property change listener to assign to a specific
// property instead of the whole map.
def propEvent
def propListener = { propEvent = it } as PropertyChangeListener

def map = [username: 'mrhaki', email: 'email@host.com', active: true] as ObservableMap
map.addPropertyChangeListener(listener)
map.addPropertyChangeListener("active", propListener)

map.location = "@work"
assert event instanceof ObservableMap.PropertyAddedEvent 
assert 'location' == event.propertyName
assert '@work' == event.newValue
assert !propEvent

map.active = false
assert event instanceof ObservableMap.PropertyUpdatedEvent 
assert propEvent instanceof ObservableMap.PropertyUpdatedEvent
assert true == propEvent.oldValue
assert false == propEvent.newValue
assert 'active' == event.propertyName

map.remove('active')
assert propEvent instanceof ObservableMap.PropertyRemovedEvent
assert 3 == map.size()

map.putAll([car: true, phone: '555-1234'])
assert event instanceof ObservableMap.MultiPropertyEvent 
assert event.events[0] instanceof ObservableMap.PropertyAddedEvent
assert 'car' == event.events[0].propertyName
assert true == event.events[0].newValue
assert event.events[1] instanceof ObservableMap.PropertyAddedEvent
assert 'phone' == event.events[1].propertyName
assert '555-1234' == event.events[1].newValue

map.clear()
assert event instanceof ObservableMap.PropertyClearedEvent
assert [username: 'mrhaki', car: true, phone: '555-1234', location: '@work', email: 'email@host.com'] == event.values

def strictMap = new ObservableMap({ name, value -> name ==~ /^a.*/ })
strictMap.addPropertyChangeListener(listener)
strictMap.putAll([a: 1, b: 2, c: 3])
assert 1 == event.events.size()
assert 'a' == event.events[0].propertyName
assert 1 == event.events[0].newValue

September 26, 2009

Groovy Goodness: Grab That Dependency

In Groovy scripts we can automatically download dependencies with Grape. Grape can be used as annotation (for a method or parameter) or with a plain method call. Apacy Ivy is used by Grape to find and download the dependencies. This means we can also use all Maven2 dependency repositories. If we want to add new repositories we must create a file ~/.groovy/grapeConfig.xml which is an Ivy configuration file and in it we can add a new repository. The downloaded files are saved in ~/.groovy/grapes.

The command-line grape command can be used to download dependencies or to list the already downloaded dependencies. For example with $ grape list we get a list of all dependencies on our local computer.

import org.apache.commons.lang.SystemUtils

@Grab(group='commons-lang', module='commons-lang', version='2.4')
def printInfo() {
    if (SystemUtils.isJavaVersionAtLeast(5)) {
        println 'We are ready to use annotations in our Groovy code.'
    } else {
        println 'We cannot use annotations in our Groovy code.'
    }
}

printInfo()

Default Grape configuration file:

<ivysettings>
  <settings defaultResolver="downloadGrapes"/>
  <resolvers>
    <chain name="downloadGrapes">
      <filesystem name="cachedGrapes">
        <ivy pattern="${user.home}/.groovy/grapes/[organisation]/[module]/ivy-[revision].xml"/>
        <artifact pattern="${user.home}/.groovy/grapes/[organisation]/[module]/[type]s/[artifact]-[revision](-[classifier]).[ext]"/>
      </filesystem>
      <!-- todo add 'endorsed groovy extensions' resolver here -->
      <ibiblio name="codehaus" root="http://repository.codehaus.org/" m2compatible="true"/>
      <ibiblio name="ibiblio" m2compatible="true"/>
      <ibiblio name="java.net2" root="http://download.java.net/maven/2/" m2compatible="true"/>
    </chain>
  </resolvers>
</ivysettings>

September 25, 2009

Groovy Goodness: Matchers for Regular Expressions

In a previous post we learned how to create a java.util.regex.Pattern object. Now we learn how to create a java.util.regex.Matcher object and use it for finding and matching values.

In Groovy we use the =~ operator (find operator) to create a new matcher object. If the matcher has any match results we can access the results by invoking methods on the matcher object. But Groovy wouldn't by groovy if we could access the results easier. Groovy enhances the Matcher class so the data is available with an array-like syntax. If we use groups in the matcher the result can be accessed with a multidimensional array. Although the result of the =~ operator is a matcher object in a conditional statement the result will be converted to a Boolean values.

We can use a second operator, ==~ (match operator), to do exact matches. With this operator the matches() method is invoked on the matcher object. The result is a Boolean value.

def finder = ('groovy' =~ /gr.*/)
assert finder instanceof java.util.regex.Matcher

def matcher = ('groovy' ==~ /gr.*/)
assert matcher instanceof Boolean

assert 'Groovy rocks!' =~ /Groovy/  // =~ in conditional context returns boolean.
assert !('Groovy rocks!' ==~ /Groovy/)  // ==~ looks for an exact match.
assert 'Groovy rocks!' ==~ /Groovy.*/

def cool = /gr\w{4}/  // Start with gr followed by 4 characters.
def findCool = ('groovy, java and grails rock!' =~ /$cool/)
assert 2 == findCool.count
assert 2 == findCool.size()  // Groovy adds size() method.
assert 'groovy' == findCool[0]  // Array-like access to match results.
assert 'grails' == findCool.getAt(1)

// With grouping we get a multidimensional array.
def group = ('groovy and grails, ruby and rails' =~ /(\w+) and (\w+)/)
assert group.hasGroup()
assert 2 == group.size()
assert ['groovy and grails', 'groovy', 'grails'] == group[0]
assert 'rails' == group[1][2]

// Use matcher methods.
assert 'Hi world' == ('Hello world' =~ /Hello/).replaceFirst('Hi')

// Groovy matcher syntax can be used in other methods.
assert ['abc'] == ['def', 'abc', '123'].findAll { it =~ /abc/ }
assert [false, false, true] == ['def', 'abc', '123'].collect { it ==~ /\d{3}/ }

September 24, 2009

Groovy Goodness: Using Regular Expression Pattern Class

To define a regular expression pattern in Groovy we can use the tilde (~) operator for a String. The result is a java.util.regex.Pattern object. The rules to define the pattern are the same as when we do it in Java code. We can invoke all standard methods on the Pattern object. For example we can create a Matcher to match values. In a next blog post we see how Groovy has better shortcuts to define a Matcher to find and match values.

def single = ~'[ab]test\\d'
assert 'java.util.regex.Pattern' == single.class.name

def dubble = ~"string\$"
assert dubble instanceof java.util.regex.Pattern

// Groovy's String slashy syntax is very useful to 
// define patterns, because we don't have to escape
// all those backslashes.
def slashy = ~/slashy \d+ value/
assert slashy instanceof java.util.regex.Pattern

// GString adds a negate() method which is mapped
// to the ~ operator.
def negateSlashy = /${'hello'}GString$/.negate()
assert negateSlashy instanceof java.util.regex.Pattern
def s = 'more'
def curlySlashy = ~"$s GString"
assert curlySlashy instanceof java.util.regex.Pattern

// Using Pattern.matcher() to create new java.util.regex.Matcher.
// In a next blog post we learn other ways to create
// Matchers in Groovy.
def testPattern = ~'t..t'
assert testPattern.matcher("test").matches()

// Groovy adds isCase() method to Pattern class.
// Easy for switch and grep statements.
def p = ~/\w+vy/
assert p.isCase('groovy')

switch ('groovy') {
    case ~/java/: assert false; break;
    case ~/gr\w{4}/: assert true; break;
    default: assert false
}

// We can use flags in our expressions. In this sample
// we use the case insensitive flag (?i). 
// And the grep method accepts Patterns.
def lang = ~/^(?i)gr.*/
def languages = ['java', 'Groovy', 'gRails']
assert ['Groovy', 'gRails'] == languages.grep(lang)

September 23, 2009

Groovy Goodness: Using GroovyMBeans for Easy JMX

JMX (Java Management eXtensions) is used to monitor and manage components. For example we can get information about the Java Virtual Machine memory usage or we can change log settings while the application is running. A JMX component is also called an MBean and Groovy makes it very easy to use these MBeans. Groovy adds the GroovyMBean class as a wrapper around MBeans. When the MBean is wrapped as a GroovyMBean accessing attributes is like accessing properties on a object and we can invoke a operation directly by its name.

In our example code we inspect some MBeans provided by the Jetty webserver. To enable JMX in Jetty we invoke the following startup command:

$ export JMX_OPTS = -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=localhost -Dcom.sun.management.jmxremote.port=8090 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false 
$ java $JMX_OPTS -jar start.jar etc/jetty-jmx.xml etc/jetty.xml

Jetty starts with an unsafe JMX connection. We can use it for this example, but for production system we must enable ssl and enable user authentication. Some Jetty components are now exposed as MBeans and in the following piece of code we inspect these MBeans. We see how to read and write attributes and how to invoke methods with GroovyMBean.

import javax.management.remote.*
import javax.management.*
import groovy.jmx.builder.*

// Setup JMX connection.
def connection = new JmxBuilder().client(port: 8090, host: 'localhost')
connection.connect()

// Get the MBeanServer.
def mbeans = connection.MBeanServerConnection

println "Total MBeans: ${mbeans.MBeanCount}\n"

// Create GroovyMBean.
def mbean = new GroovyMBean(mbeans, 'org.mortbay.jetty.webapp:type=webappcontext,name=test,id=0')
println mbean  // Outputs all attributes and operations.

assert mbean.running  // Get attribute value.
assert '/test' == mbean.contextPath
mbean.contextPath = '/changed'  // Set attribute value.
assert '/changed' == mbean.contextPath
mbean.stop()  // Invoke stop() method.
assert !mbean.running
mbean.setContextAttribute 'groovy', true  // Invoke setContextAttribute(String, Object) method.
assert mbean.contextAttributes.groovy

// Find MBeans with Groovy collection methods.
def webBean = mbeans.queryNames(new ObjectName('org.mortbay.jetty.webapp:*'), null).find {
    it.getKeyProperty('name') == 'test-jndi' &&
    it.getKeyProperty('type') == 'webappcontext'
}
mbean = new GroovyMBean(mbeans, webBean)
assert mbean

// Classical way to invoke operations and access attributes,
// which is less readable than the GroovyMBean version.
assert mbeans.getAttribute(webBean, "running")
mbeans.invoke(webBean, "setContextAttribute", ['groovy', Boolean.TRUE] as Object[], ['java.lang.String', 'java.lang.Object'] as String[])
assert (mbeans.getAttribute(webBean, "contextAttributes").get("groovy"))
mbeans.setAttribute(webBean, new Attribute("distributable", Boolean.TRUE))
assert (mbeans.getAttribute(webBean, "distributable"))

def gmbeans = mbeans.queryNames(new ObjectName('org.mortbay.jetty.webapp:*'), null).inject([]) { result, name ->
    result << new GroovyMBean(mbeans, name)
}
println ''
gmbeans.each { 
    println "${it.displayName} is ${it.running ? 'running' : 'stopped'}" 
}

When we run this script we get the following output:

Total MBeans: 107

MBean Name:
  org.mortbay.jetty.webapp:id=0,name=test,type=webappcontext
  
Attributes:
  (rw) [Ljava.lang.String; systemClasses
  (rw) java.lang.String overrideDescriptor
  (rw) java.lang.String descriptor
  (rw) [Ljava.lang.String; configurationClasses
  (rw) java.io.File tempDirectory
  (rw) java.lang.String war
  (rw) boolean extractWAR
  (rw) [Ljava.lang.String; serverClasses
  (rw) boolean distributable
  (rw) boolean parentLoaderPriority
  (rw) java.lang.String extraClasspath
  (rw) java.lang.String defaultsDescriptor
  (rw) boolean copyWebDir
  (rw) javax.management.ObjectName securityHandler
  (rw) javax.management.ObjectName servletHandler
  (rw) javax.management.ObjectName sessionHandler
  (rw) [Ljava.lang.String; connectorNames
  (rw) java.util.Map initParams
  (rw) java.lang.String resourceBase
  (rw) [Ljava.lang.String; welcomeFiles
  (r) java.util.Map contextAttributes
  (rw) java.lang.String contextPath
  (r) java.lang.String displayName
  (rw) [Ljava.lang.String; virtualHosts
  (rw) boolean shutdown
  (rw) javax.management.ObjectName handler
  (r) boolean stopped
  (r) boolean failed
  (r) boolean starting
  (r) boolean started
  (r) boolean stopping
  (r) boolean running
  (r) javax.management.ObjectName server
Operations:
  void setContextAttribute(java.lang.String name, java.lang.String value)
  void setContextAttribute(java.lang.String name, java.lang.Object value)
  void removeContextAttribute(java.lang.String name)
  void stop()
  void start()
  void destroy()

Test WebApp is stopped
JAAS Test is running
Cometd Test WebApp is running
Test JNDI WebApp is running

September 22, 2009

Groovy Goodness: MultiMethods or Multiple Dispatch

Multimethods or multiple dispatch is a mechanism where at runtime the correct method is choosen based on the runtime type of the arguments of the method. Dynamic languages can do this at runtime and because Groovy is a dynamic language we can use multimethods in Groovy. We define overloaded methods with differently typed arguments and let Groovy decided at runtime which method to invoke. This subject is best explained by an example:

// We start off by some very simple class definitions
// with a one-level hierarchy amongst them.
abstract class Person {
    String name
}
class Parent extends Person {}
class Child extends Person {}

// Now we define methods to return the name with some extra info.
def printName(Person person) { "printName(Person): $person.name" }
def printName(Child child) { "printName(Child): $child.name" }
def printName(p) { "printName(p): $p.name" }

// Create new Parent and Child objects but use Person type reference.
Person parent1 = new Parent(name: 'parent1')
Person child1 = new Child(name: 'child1')

assert 'printName(Person): parent1' == printName(parent1)
assert 'printName(Child): child1' == printName(child1)  // This is not what Java would do!! 
assert 'printName(Person): child1' == printName(child1 as Person)  // Same as what Java would do with printName(child1)

// Create objects with type reference is equal to object.
Parent parent2 = new Parent(name: 'parent2')
Child child2 = new Child(name: 'child2')

assert 'printName(Person): parent2' == printName(parent2)
assert 'printName(Child): child2' == printName(child2) 

// Use class outside Person hierarchy.
class Dog { 
    String name 
}
assert 'printName(p): buck' == printName(new Dog(name: 'buck'))

September 21, 2009

Groovy Goodness: Parsing Commandline Arguments with CliBuilder

Groovy is a great language to create scripts. Most of the time if we invoke the scripts we pass arguments to the script. These arguments are available as a String[] array in our script. For example to get the first argument we can use the following code s = args[0]. To have real argument handling in our script we use Groovy's CliBuilder class. This class uses Jakarta Commons CLI under the hood. With CliBuilder we can define the argument options and parse the arguments. CliBuilder adds Groovyness by allowing us to invoke non-existing one-letter methods, which are turned into argument options with the one-letter shortcut. Furthermore we can use named parameters to define usage text, parser implementation, formatter implementation and option properties.

Let's see the CliBuilder in action. We create a script to show a date formatted according to defined arguments. If we don't define a date the current date is assumed. And furthermore we want to be able to define a prefix text, which is added before the formatted date (is empty by default).

import java.text.*

def showdate(args) {
    def cli = new CliBuilder(usage: 'showdate.groovy -[chflms] [date] [prefix]')
    // Create the list of options.
    cli.with {
        h longOpt: 'help', 'Show usage information'
        c longOpt: 'format-custom', args: 1, argName: 'format', 'Format date with custom format defined by "format"'
        f longOpt: 'format-full',   'Use DateFormat#FULL format'
        l longOpt: 'format-long',   'Use DateFormat#LONG format'
        m longOpt: 'format-medium', 'Use DateFormat#MEDIUM format (default)'
        s longOpt: 'format-short',  'Use DateFormat#SHORT format'
    }
    
    def options = cli.parse(args)
    if (!options) {
        return
    }
    // Show usage text when -h or --help option is used.
    if (options.h) {
        cli.usage()
        // Will output:
        // usage: showdate.groovy -[chflms] [date] [prefix]
        //  -c,--format-custom <format>   Format date with custom format defined by "format"
        //  -f,--format-full              Use DateFormat#FULL format   
        //  -h,--help                     Show usage information   
        //  -l,--format-long              Use DateFormat#LONG format   
        //  -m,--format-medium            Use DateFormat#MEDIUM format   
        //  -s,--format-short             Use DateFormat#SHORT format   
        return
    }
    
    // Determine formatter.
    def df = DateFormat.getDateInstance(DateFormat.MEDIUM)  // Defeault.
    if (options.f) {  // Using short option.
        df = DateFormat.getDateInstance(DateFormat.FULL) 
    } else if (options.'format-long') {  // Using long option.
        df = DateFormat.getDateInstance(DateFormat.LONG) 
    } else if (options.'format-medium') {
        df = DateFormat.getDateInstance(DateFormat.MEDIUM) 
    } else if (options.s) {
        df = DateFormat.getDateInstance(DateFormat.SHORT) 
    } else if (options.'format-custom') {
        df = new SimpleDateFormat(options.c)
    }

    // Handle all non-option arguments.
    def prefix = ''  // Default is empty prefix.
    def date = new Date()  // Default is current date.
    def extraArguments = options.arguments()
    if (extraArguments) {
        date = new Date().parse(extraArguments[0])
        // The rest of the arguments belong to the prefix.
        if (extraArguments.size() > 1) {
            prefix = extraArguments[1..-1].join(' ')
        }
    }
    
    "$prefix${df.format(date)}"
}

// Set locale for assertions.
Locale.setDefault(Locale.US)
assert '12/1/09' == showdate(['--format-short', '2009/12/1'])
assert '12/1/09' == showdate(['-s', '2009/12/1'])
assert 'Dec 1, 2009' == showdate(['2009/12/1'])
assert 'Dec 1, 2009' == showdate(['--format-medium', '2009/12/1'])
assert 'Dec 1, 2009' == showdate(['-m', '2009/12/1'])
assert 'December 1, 2009' == showdate(['--format-long', '2009/12/1'])
assert 'December 1, 2009' == showdate(['-l', '2009/12/1'])
assert 'Tuesday, December 1, 2009' == showdate(['--format-full', '2009/12/1'])
assert 'Tuesday, December 1, 2009' == showdate(['-f', '2009/12/1'])
assert 'Default date format: Dec 1, 2009' == showdate(['2009/12/1', 'Default', 'date', 'format: '])
assert 'Important date: Dec 1, 2009' == showdate(['-m', '2009/12/1', 'Important date: '])
assert 'week 49 of the year 2009 AD' == showdate(['-c', "'week' w 'of the year' yyyy G", '2009/12/1'])
assert '2009/12/01' == showdate(['--format-custom', 'yyyy/MM/dd', '2009/12/01'])
assert '2009' == showdate(['-cyyyy', '2009/12/1'])
assert new Date().format('yyyy/MM/dd') == showdate(['--format-custom', 'yyyy/MM/dd'])

println showdate(args) 

September 20, 2009

Groovy Goodness: Padding Strings

Groovy extends the String class with a couple of padding methods. These methods allows us to define a fixed width a String value must occupy. If the String itself is less than the fixed width then the space is padded with spaces or any other character or String we define. We can pad to the left or the right of the String or both left and right and put the String in the center.

These methods are especially useful when we create Groovy scripts that run on the console and we want to format some output.

assert '   Groovy   ' == 'Groovy'.center(12)
assert 'Groovy      ' == "Groovy".padRight(12)
assert '      Groovy' == /Groovy/.padLeft(12)

assert '---Groovy---' == "Groovy".center(12, '-')
assert 'Groovy * * *' == "Groovy".padRight(12, ' *')
assert 'Groovy Groovy Groovy' == 'Groovy'.padLeft(20, 'Groovy ')

def createOutput = {
    def table = [
        // Page,    Response time, Size
        ['page1.html',        200, 1201],
        ['page2.html',         42, 8853],
        ['page3.html',         98, 3432],
        ['page4.html',        432, 9081]
    ]

    def total = { data, index ->
        data.inject(0) { result, row -> result += row[index] }
    }
    def totalTime = total.curry(table, 1)
    def totalSize = total.curry(table, 2)

    def out = new StringBuffer()
    out << ' Summary '.center(15, "*") << '\n\n'
    out << 'Total pages:'.padRight(25)
    out << table.size().toString().padLeft(6) << '\n'
    out << 'Total response time (ms):'.padRight(25)
    out << totalTime().toString().padLeft(6) << '\n'
    out << 'Total size (KB):'.padRight(25)
    out << totalSize().toString().padLeft(6) << '\n\n'

    out << ' Details '.center(15, "*") << '\n\n'
    table.each {
        out << it[0].padRight(14)
        out << it[1].toString().padLeft(5)
        out << it[2].toString().padLeft(8)
        out << '\n'
    }
    out.toString()
}

assert '''\
*** Summary ***

Total pages:                  4
Total response time (ms):   772
Total size (KB):          22567
         
*** Details ***

page1.html      200    1201
page2.html       42    8853
page3.html       98    3432
page4.html      432    9081
''' == createOutput()

September 19, 2009

Groovy Goodness: Working with Arrays

Groovy supports arrays just like in Java. We only get a lot more methods because of the GDK extensions added to arrays. The only we thing we need to consider is the way we initialize arrays. In Java we can define and populate an array with the following code: String[] s = new String[] { "a", "b" };, but in Groovy we cannot use this syntax. In Groovy the previous statement would become String[] s = ["a", "b"] as String[].

def strArray = new String[3]
assert strArray instanceof String[]
strArray[0] = 'mrhaki'
strArray.putAt(1, 'Groovy')  // New syntax.
strArray[2] = 'Java'

assert 'mrhaki' == strArray.getAt(0)  // Just another way to get a value.
assert 'Groovy' == strArray[1]
assert 'Java' == strArray[-1]  // Negative indeces allowed.
assert ['mrhaki', 'Groovy'] == strArray[0..1]  // We can use ranges.
assert ['mrhaki', 'Java'] == strArray[0, 2]

assert 3 == strArray.length  // Normal length property for arrays.
assert 3 == strArray.size()  // Groovy adds size() method as well.

// We can use min() and max() methods.
assert 42 == [102,301,42,83].min()
assert 301 == [102,301,42,83].max()
assert 'Java' == strArray.min { it.size() }
assert 'mrhaki' == strArray.max { it[0] as char }

// We can even use the Collection GDK methods on an array.
strArray.eachWithIndex { value, idx -> assert value == strArray[idx] }
assert ['ikahrm', 'yvoorG', 'avaJ'] == strArray.collect { it.reverse() }
assert 'Groovy' == strArray.find { it =~ /Groovy/ }

// We can remove values with the '-' operator.
assert ['Groovy', 'Java'] == strArray - 'mrhaki'

// Other useful methods for arrays.
assert ['Java', 'Groovy', 'mrhaki'] == strArray.reverse()
assert ['Groovy', 'Java', 'mrhaki'] == strArray.sort()
assert 1 == strArray.count('mrhaki')

// Convert to ArrayList.
def strList = strArray.toList()
assert 'java.util.ArrayList' == strList.class.name

// Convert ArrayList to array object.
def otherArray = strList as String[]
assert otherArray instanceof String[]

September 18, 2009

Cool Assertion Stacktrace Output in Groovy Web Console

The Groovy Web Console application is very cool. We can use it to test and run Groovy scripts right in our web browser. Today I noticed a new feature that makes using assertions even more fun. If a assertion is false the StackTrace tab shows very detailed information about why the assertion is false. The value of each object used in the assertion and results from operators are shown.

Suppose we have the following script:

class User implements Comparable {
    String username
    int compareTo(other) { this.username <=> other.username }
    String toString() { "$username" }
}

assert 0 == (new User(username: 'mrhaki') <=> new User(username: 'hubert'))

The assertion is false and in the StackTrace tab we see why:

Assertion failed: 

assert 0 == (new User(username: 'mrhaki') <=> new User(username: 'hubert'))
         |   |                            |   |
         |   mrhaki                       1   hubert
         false

 at Script1.run(Script1.groovy:7)

Very impressive! Run this script in Groovy Web Console.

Groovy Goodness: Lazy Initialization of Properties

Sometimes we want the value of a property only to be calculated on first use. The calculation of the value can be time consuming or requires a lot of resources. In Groovy we can use the @Lazy transformation to define a property we want to be initialized lazily. The value is not calculated or assigned until the value is requested. The transformation also allows a soft parameter. This defines the field as soft reference.

class Get {
    String url
    @Lazy URL urlObj = { url?.toURL() }()  // Closures allowed to create object.
    // Will use a soft reference.
    @Lazy(soft=true) String text = urlObj?.text
}

def g = new Get(url: 'http://mrhaki.blogspot.com/') 
assert 'http://mrhaki.blogspot.com/' == g.url
assert g.dump().contains('text=null')
assert g.dump().contains('urlObj=null')

// Now we access the urlObj property, so the value
// is calculated and we can access it.
assert g.urlObj
assert 'http' == g.urlObj.protocol
assert 'mrhaki.blogspot.com' == g.urlObj.host
assert '/' == g.urlObj.path

// Now we access the text property, so the contents
// is fetched from the URL.
assert g.text
assert g.text.contains('Messages from mrhaki')

September 17, 2009

Groovy Goodness: Making a Class Immutable

Immutable objects are created and cannot change after creation. This makes immutable objects very usable in concurrent and functional programming. To define a Java class as immutable we must define all properties as readonly and private. Only the constructor can set the values of the properties. The Groovy documentation has a complete list of the rules applying to immutable objects. The Java code to make a class immutable is verbose, especially since the hashCode(), equals() and toString() methods need to be overridden.

Groovy has the @Immutable transformation to do all the work for us. We only have to define @Immutable in our class definition and any object we create for this class is an immutable object. Groovy generates a class file following the rules for immutable objects. So all properties are readonly, constructors are created to set the properties, implementations for the hashCode(), equals() and toString() methods are generated, and more.

@Immutable class User {
    String username, email
    Date created = new Date()
    Collection roles
}

def first = new User(username: 'mrhaki', email: 'email@host.com', roles: ['admin', 'user'])
assert 'mrhaki' == first.username
assert 'email@host.com' == first.email
assert ['admin', 'user'] == first.roles
assert new Date().after(first.created)
try {
    // Properties are readonly.
    first.username = 'new username'
} catch (ReadOnlyPropertyException e) {
    assert 'Cannot set readonly property: username for class: User' == e.message
}
try {
    // Collections are wrapped in immutable wrapper classes, so we cannot
    // change the contents of the collection.
    first.roles << 'new role'
} catch (UnsupportedOperationException e) {
    assert true
}


def date = new Date(109, 8, 16)
def second = new User('user', 'test@host.com', date, ['user'])
assert 'user' == second.username
assert 'test@host.com' == second.email
assert ['user'] == second.roles
assert '2009/08/16' == second.created.format('yyyy/MM/dd')
assert date == second.created
assert !date.is(second.created)  // Date, Clonables and arrays are deep copied.
// toString() implementation is created.
assert 'User(user, test@host.com, Wed Sep 16 00:00:00 UTC 2009, [user])' == second.toString() 


def third = new User(username: 'user', email: 'test@host.com', created: date, roles: ['user'])
// equals() method is also generated by the annotation and is based on the
// property values.
assert third == second

September 16, 2009

Groovy Goodness: Looping in Different Ways

Looping in Groovy can be done in several ways. We can use the standard classic Java for loop or use the newer Java for-each loop. But Groovy adds more ways to loop several times and execute a piece of code. Groovy extends the Integer class with the step(), upto() and times() methods. These methods take a closure as a parameter. In the closure we define the piece of code we want to be executed several times.

If we have a List in Groovy we can loop through the items of the list with the each() and eachWithIndex() methods. We also need to pass a closure as parameter to the methods. The closure is then executed for every item in the list.

// Result variable for storing loop results.
def result = ''
// Closure to fill result variable with value.
def createResult = { 
    if (!it) {  // A bit of Groovy truth: it == 0 is false
        result = '0'
    } else {
        result += it
    }
}

// Classic for loop.
for (i = 0; i < 5; i++) {
    createResult(i)
}
assert '01234' == result

// Using int.upto(max).
0.upto(4, createResult)
assert '01234' == result

// Using int.times.
5.times(createResult)
assert '01234' == result

// Using int.step(to, increment).
0.step 5, 1, createResult
assert '01234' == result

// Classic while loop.
def z = 0
while (z < 5) {
    createResult(z)
    z++
}
assert '01234' == result

def list = [0, 1, 2, 3, 4]

// Classic Java for-each loop.
for (int i : list) {
    createResult(i)
}
assert '01234' == result

// Groovy for-each loop.
for (i in list) {
    createResult(i)
}
assert '01234' == result

// Use each method to loop through list values.
list.each(createResult)
assert '01234' == result

// Ranges are lists as well.
(0..4).each(createResult)
assert '01234' == result

// eachWithIndex can be used with closure: first parameter is value, second is index.
result = ''
list.eachWithIndex { listValue, index -> result += "$index$listValue" }
assert '0011223344' == result

September 15, 2009

Groovy Goodness: Check for Object Equality

Groovy overloads the == operator and maps it to the equals() method. This is very different from Java, so when developers are switching back and forth between Groovy and Java mistakes are bound to happen. In Java we use the == operator to see if variables are referring to the same object instance. In Groovy we use the == operator to see if two objects are the same, in Java we would use the equals() method for this. To test if two variables are referring to the same object instance in Groovy we use the is() method. The != operator is also overloaded and maps to the !equals() statement.

And because we are in Groovy land all null values are handled gracefully. We don't have to write extra checks to check for null values before we can test for equality.

Integer myInt = 42
Integer anotherInt = myInt
Integer newInt = 42
Integer different = 101

assert myInt == anotherInt  // In Java: myInt != null && myInt.equals(anotherInt)
assert myInt.is(anotherInt)  // In Java: myInt == anotherInt

assert myInt == newInt

assert myInt != different

September 14, 2009

Groovy Goodness: Named Parameters are Converted to Map

We can use named parameters when we invoke a Groovy method, but Groovy doesn't invoke the method with just those parameters. Groovy collects all named parameters and puts them in a Map. The Map is passed on to the method as the first argument. The method needs to know how to get the information from the Map and process it. There is one rule: the first parameter of the method must be the Map parameter, because Groovy will put the Map as first argument in the method invocation. Other parameters are appended in the same order as defined in the method invocation.

class Address {
    String street, city
    int number    
}

class Person {
    String name
    Address address
    String phoneNumber
    
    def move(newAddress, newPhoneNumber) {
        address.street = newAddress.street
        address.number = newAddress['number']
        address.city   = newAddress."city"
        phoneNumber = newPhoneNumber
    }
}

def a = new Address(street: 'Main St.', number: 1, city: 'Duck City')
def p = new Person(name: 'mrhaki', address: a, phoneNumber: '555-123499102')

p.move(street: 'High Av.', city: 'New Yark', '00920120', number: 42)  
// Groovy transform the method invocation to:
// p.move([street: 'High Av.', number: 42, city: 'New Yark'], '555-00920120')

assert 'High Av.' == p.address.street
assert 42 == p.address.number
assert 'New Yark' == p.address.city
assert '555-00920120' == p.phoneNumber
assert 'mrhaki' == p.name

September 13, 2009

Groovy Goodness: Exception Handling

Handling exceptions in Groovy is the same as in Java. We write a try-catch block to catch an exception and handle it. But there is a twist: in Groovy every exception is optional. This goes for checked exceptions as well. Groovy will pass an exception to the calling code until it is handled, but we don't have to define it in our method signature. So we as developers can choose how and when to handle the exception.

We all have seen code where developers have to handle checked exceptions, because otherwise the Java source code will not compile. And what ends up in the catch block? Mostly what the IDE generates, or ex.printStackTrace(), or any other code that handles the exception without any thought. In Groovy we can choose at which level we want to catch an exception. If we don't do anything the exception will be passed on to the calling code. So without a compiler grinding to a halt with errors about exception handling we must have a good discipline to do this ourselves in Groovy.

try {
    def url = new URL('malformedUrl')
    assert false, 'We should never get here because of the exception.'
} catch (MalformedURLException e) {
    assert true
    assert e in MalformedURLException
}

// Method throws MalformedURLException, but we don't 
// have to define it. Groovy will pass the exception
// on to the calling code.
def createUrl() {
    new URL('malformedUrl')
}

try {
    def url1 = createUrl()
    assert false, 'We should never get here because of the exception.'
} catch (all) {  // Groovy shortcut: we can omit the Exception class 
                 // if we want to catch all Exception and descendant objects. 
                 // In Java we have to write catch (Exception all).
    assert true
    assert all in MalformedURLException
}

Run this script in GroovyConsole.

September 12, 2009

Groovy Goodness: Parameters with Default Values

In Groovy we can assign default values to parameters in a method. If we define a default value for a parameter Groovy basically supports two method signatures: one with all parameters and one where the parameter with a default value is omitted. If we use multiple parameters with default values then the right most parameter with a default value is first eliminated then the next and so on.

def say(msg = 'Hello', name = 'world') {
    "$msg $name!"
}

// We can invoke 3 signatures:
// say(), say(msg), say(msg, name)
assert 'Hello world!' == say()
// Right most parameter with default value is eliminated first.
assert 'Hi world!' == say('Hi')
assert 'Howdy, mrhaki!' == say('Howdy,', 'mrhaki')

Run this script in GroovyConsole.

September 11, 2009

Groovy Goodness: Optional return Keyword

In Groovy we can omit the return keyword at the end of a method, it is optional. It is no problem to leave it in, but we can leave it out without any problems. Since Groovy 1.6 this is even true when the last statement of a method is a conditional statement or a try-catch block.

def simple() {
    "Hello world"
}
assert 'Hello world' == simple()


def doIt(b) {
    if (b) {
        "You are true"
    } else {
        "You are false"
    }
}
assert 'You are true' == doIt(true)
assert 'You are false' == doIt(false)


def tryIt(file) {
    try {
        new File(file).text
    } catch (e) {
        "Received exception: ${e.message}"
    } finally {
        println 'Finally is executed but nothing is returned.'
        'Finally reached'
    }
}
assert 'Received exception: invalidfilename (The system cannot find the file specified)'  == tryIt('invalidfilename') 
// Create new file with the name test.
def newFile = new FileWriter('test').withWriter { it.write('file contents') }
assert 'file contents' == tryIt('test')

September 10, 2009

Groovy Goodness: Using the GroupBy Method

In Groovy we can group the elements of a Collection type in a map. We define the rule for grouping with a closure. The result is a map where the key is the grouping condition and the value contains the elements of the Collection type belonging to the key. Let's see the groupBy method in action:

class User {
    String name
    String city
    Date birthDate
    public String toString() { "$name" }
}

def users = [
    new User(name:'mrhaki', city:'Tilburg', birthDate:new Date(73,9,7)),
    new User(name:'bob', city:'New York', birthDate:new Date(63,3,30)),
    new User(name:'britt', city:'Amsterdam', birthDate:new Date(80,5,12)),
    new User(name:'kim', city:'Amsterdam', birthDate:new Date(83,3,30)),
    new User(name:'liam', city:'Tilburg', birthDate:new Date(109,3,6))
]

// Helper closure for asserts.
def userToString = { it.toString() }

// Group by city property of user object:
def usersByCity = users.groupBy({ user -> user.city })
assert 2 == usersByCity["Tilburg"].size()
assert ['mrhaki', 'liam'] == usersByCity["Tilburg"].collect(userToString) 
assert ['bob'] == usersByCity["New York"].collect(userToString)
assert ['britt', 'kim'] == usersByCity["Amsterdam"].collect(userToString)

// Group by year of birthdate property of user object:
def byYear = { u -> u.birthDate[Calendar.YEAR] }
def usersByBirthDateYear = users.groupBy(byYear)
assert ['mrhaki'] == usersByBirthDateYear[1973].collect(userToString)

// Just a little fun with the closure:
def groupByGroovy = { 
    if (it =~ /y/) {
        "Contains y"
    } else {
        "Doesn't contain y"
    }
}
assert ["Contains y":["Groovy"], "Doesn't contain y":["Java", "Scala"]] == ['Groovy', 'Java', 'Scala'].groupBy(groupByGroovy)

Run this script in GroovyConsole.

September 9, 2009

Groovy Goodness: the as Keyword

We can change the type of objects with the as keyword in Groovy. We can even make maps and closure look like interface implementations when we use as. Furthermore we can use as to create an alias for an import statement.

import java.text.MessageFormat as mf // Alias mf

// Use alias and use as to convert list to Object[]:
assert 'Simple message!' == mf.format('Simple {0}!', ['message'] as Object[])

// Normal Groovy list:
def intList = [1,2,3,4]
assert 'java.util.ArrayList' == intList.class.name
assert 4 == intList.size()

// Coerse to int[]:
def intArray = intList as int[]
assert 'java.util.ArrayList' != intArray.class.name
assert 4 == intArray.length  // Use int[] property.

// Use as to create Date object from list:
def date = [109, 8, 6] as Date
assert 2009 == date[Calendar.YEAR]
assert 8 == date[Calendar.MONTH]
assert 6 == date[Calendar.DATE]

// Use as to treat closure as implementation for
// the Runnable interface:
def t = new Thread({ println 'hello' } as Runnable)
t.start()  // Output: hello

// Use as to treat map as implementation for
// the Runnable interface:
def t2 = new Thread([run: { println 'hello' }] as Runnable)
t2.start()  // Output: hello

September 8, 2009

Groovy Goodness: Using Lists and Maps As Constructors

Constructors in Groovy can be invoked in a classic Java way, but we can also use lists or maps to create objects. Groovy supports an explicit coersion of a list to a constructor with the as keyword. Or we can rely on the implicit coersion when Groovy looks at the type of the variable to automatically convert the list to the right constructor call.

// Default constructor invocation:
def url1 = new URL('http', 'www.mrhaki.com', 80, '/')
assert 'http' == url1.protocol
assert 'www.mrhaki.com' == url1.host
assert 80 == url1.port
assert '/' == url1.file
assert '/' == url1.path

// Explicit coersion with as keyword:
def url2 = ['http', 'www.mrhaki.com', 80, '/'] as URL
assert 'http' == url1.protocol
assert 'www.mrhaki.com' == url2.host
assert 80 == url2.port
assert '/' == url2.file
assert '/' == url2.path

// Implicit coersion by type of variable:
URL url3 = ['http', 'www.mrhaki.com', 80, '/'] 
assert 'http' == url3.protocol
assert 'www.mrhaki.com' == url3.host
assert 80 == url3.port
assert '/' == url3.file
assert '/' == url3.path    

When we use GroovyBeans syntax we can use a map with named parameter to invoke the constructor. But we can also use the explicit and implicit coersions Groovy provides.

// GroovyBean: Groovy creates a constructor
// that takes a map as parameter.
class Sample {
    Integer age 
    String name
}

def s1 = new Sample([age: 36, name: 'mrhaki'])
assert 36 == s1.age
assert 'mrhaki' == s1.name

// Explicit coersion with as keyword:
def s2 = [age: 36, name: 'mrhaki'] as Sample
assert 36 == s2.age
assert 'mrhaki' == s2.name

// Implicit coersion (by type of variable):
Sample s3 = [age: 36, name: 'mrhaki']
assert 36 == s3.age
assert 'mrhaki' == s3.name

September 7, 2009

Groovy Goodness: Add Some Curry for Taste

Currying is a technique to create a clone of a closure and fixing values for some of the parameters. We can fix one or more parameters, depending on the number of arguments we use for the curry() method. The parameters are bound from left to right. The good thing is we can even use other closures as parameters for the curry() method.

Let's see some curry() action in the following sample:

// Simple sample.
def addNumbers = { x, y -> x + y }
def addOne = addNumbers.curry(1)
assert 5 == addOne(4)


// General closure to use a filter on a list.
def filterList = { filter, list -> list.findAll(filter) }
// Closure to find even numbers.
def even = { it % 2 == 0 }
// Closure to find odd numbers.  
def odd = { !even(it) }  
// Other closures can be curry parameters.
def evenFilterList = filterList.curry(even)
def oddFilterList = filterList.curry(odd)
assert [0,2,4,6,8] == evenFilterList(0..8)
assert [1,3,5,7] == oddFilterList(0..8)


// Recipe to find text in lines.
def findText = { filter, handler, text -> 
    text.eachLine {
        filter(it) ? handler(it) : null
    }
}
// Recipe for a regular expression filter.
def regexFilter = { pattern, line -> line =~ pattern }

// Create filter for searching lines with "Groovy".
def groovyFilter = regexFilter.curry(/Groovy/)
// Create handler to print out line.
def printHandler = { println "Found in line: $it" }

// Create specific closure as clone of processText to
// search with groovyFilter and print out found lines.
def findGroovy = findText.curry(groovyFilter, printHandler)

// Invoke the closure.
findGroovy('''Groovy rules!
And Java?
Well... Groovy needs the JVM... 
''')

// This will output:
// Found in line: Groovy rules!
// Foudn in line: Well... Groovy needs the JVM...

Run this script on GroovyConsole.

September 6, 2009

Groovy Goodness: Using the Inject Method

Groovy has some features and methods we can categorize as functional programming. The inject() method is a so called higher-order function. Other languages call it a fold, reduce or accumulate. The inject() method processes a data structure with a closure and builds up a return value. The first parameter of the inject() method is the first value of the intermediary results of the second parameter: the closure. When we use the inject() we don't introduce any side effects, because we build up the value without using any outside variable.

To understand the inject() method better we look at some sample code:

// Traditional "sum of the values in a list" sample.
// First with each() and side effect, because we have
// to declare a variable to hold the result:
def total = 0
(1..4).each { total += it }
assert 10  == total

// With the inject method we 'inject' the 
// first value of the result, and then for
// each item the result is increased and
// returned for the next iteration.
def sum = (1..4).inject(0) { result, i -> result + i }
assert 10 == sum

// We add a println statement to see what happens.
(1..4).inject(0) { result, i ->
    println "$result + $i = ${result + i}"
    result + i
}
// Output: 
// 0 + 1 = 1
// 1 + 2 = 3
// 3 + 3 = 6
// 6 + 4 = 10


class Person {
    String username
    String email
}
def persons = [
    new Person(username:'mrhaki', email: 'email@host.com'),
    new Person(username:'hubert', email: 'other@host.com')
]

// Convert list to a map where the key is the value of
// username property of Person and the value is the email
// property of Person. We inject an empty map as the starting
// point for the result.
def map = persons.inject([:]) { result, person ->
    result[person.username] = person.email
    result
}
assert [mrhaki: 'email@host.com', hubert: 'other@host.com'] == map

Run this script on GroovyConsole.

September 5, 2009

Groovy Goodness: the With Method

Groovy has a with method we can use to group method calls and property access to an object. The with method accepts a closure and every method call or property access in the closure applies to the object if applicable. The method is part of Groovy's extensions to the java.lang.Object class. Let's see this with an example:

class Sample {
    String username
    String email
    List<String> labels = []
    def speakUp() { "I am $username" }
    def addLabel(value) { labels << value }
}

def sample = new Sample()
sample.with {
    username = 'mrhaki'
    email = 'email@host.com'
    println speakUp()  // Output: I am mrhaki
    addLabel 'Groovy' 
    addLabel 'Java'    
}
assert 2 == sample.labels.size()
assert 'Groovy' == sample.labels[0]
assert 'Java' == sample.labels[1]
assert 'mrhaki' == sample.username
assert 'email@host.com' == sample.email

def sb = new StringBuilder()
sb.with {
    append 'Just another way to add '
    append 'strings to the StringBuilder '
    append 'object.'    
}

assert 'Just another way to add strings to the StringBuilder object.' == sb.toString()

// Another example as seen at 
// http://javajeff.blogspot.com/2008/11/getting-groovy-with-with.html
def cal = Calendar.instance
cal.with {
    clear()
    set(YEAR, 2009)
    set MONTH, SEPTEMBER
    set DATE, 4    
    add DATE, 2
}
assert'September 6, 2009' == cal.time.format('MMMM d, yyyy')

September 4, 2009

Groovy Goodness: Keep Your Values in Ranges

Ranges are lists with sequential values. Each range is also a list object, because Range extends java.util.List. A range can be inclusive (so both begin and end values are in the range) or exclusive (the end value is not in the range). We use .. for an inclusive range and ..< for an exclusive range.

Each object that implements the Comparable interface and implements a next() and previous() method can be used for a range. So this means we can write our own objects so they can be used in ranges, but also we can use for example String objects or Enum values in a range.

// Simple ranges with number values.
def ints = 1..10
assert [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] == ints
assert 10 == ints.size()
assert 1  == ints.from
assert 10 == ints.to

// We can step through the values.
def list = []
ints.step(2) { list << it }
assert [1, 3, 5, 7, 9] == list

// A range is just a List.
assert 1  == ints[0]
assert 10 == ints.last()
def s = ''
(2..4).each { s += it }
assert '234' == s

// Exclusive range.
def exclusive = 2..<8
assert [2, 3, 4, 5, 6, 7] == exclusive
assert 6 == exclusive.size()
assert !exclusive.contains(8)

// Object with next() and previous() can be used
// in ranges. Groovy extends Java enum with 
// next() and previous() so we can use it in ranges.
enum Compass {
    NORTH, NORTH_EAST, EAST, SOUTH_EAST, 
    SOUTH, SOUTH_WEST, WEST, NORTH_WEST
}
def northToSouth = Compass.NORTH..Compass.SOUTH
assert 5 == northToSouth.size()
assert Compass.EAST == northToSouth[2]
assert northToSouth.contains(Compass.SOUTH_EAST)

// Bonus: next() and previous() are equivalent to 
// ++ and -- operators.
def region = Compass.SOUTH
assert Compass.SOUTH_WEST == ++region
assert Compass.SOUTH == --region

September 3, 2009

Groovy Goodness: the Spread Operator

In a previous post we learned about the spread-dot operator, in this post we look at the spread operator. The spread operator (*) is used to tear a list apart into single elements. This can be used to invoke a method with multiple parameters and then spread a list into the values for the parameters. The spread operator can also be used to add lists or ranges to lists and to add maps to other maps.

class Simple {
    String speak(Integer n, String text, Date date) {
        def out = new StringBuffer()
        n.times { 
            out << "Say $text on ${date.format('yyyy-MM-dd')}.\n" 
        }
        out
    }
}

// Spread params list for speak() method.
def params = [
    2,
    "hello world",
    new Date().parse("yyyy/MM/dd", "2009/09/01")
]
assert '''Say hello world on 2009-09-01.
Say hello world on 2009-09-01.
''' == new Simple().speak(*params)

// Add a list to another list.
def list = ['Groovy', 'Java']
assert ['Groovy', 'Java', 'Scala'] == [*list, 'Scala']

// Add a range to a list.
def range = 2..5
assert [1, 2, 3, 4, 5, 6] == [1, *range, 6]

// Add a map to another map.
def map = [name: 'mrhaki', blog: true]
assert [name: 'mrhaki', blog: true, subject: 'Groovy Goodness'] == [subject: 'Groovy Goodness', *:map]

// Little trick to simulate named parameters for a method.
// It is just a trick so the ordering of the map key/values
// must be the same as the method parameters.
def paramsMap = [
    n: 1, 
    text: 'hello', 
    date: new Date().parse("yyyy/MM/dd", "2009/09/04")
]
def paramsList = paramsMap.values().toList()
assert 'Say hello on 2009-09-04.\n' == new Simple().speak(*paramsList)

September 2, 2009

Groovy Goodness: Date and Time Durations and the TimeCategory

Groovy has some elegant ways to work with date and time values. One of them is the support of durations. We can define a duration to denote a certain time amount, like 7 days, 2 hours and 50 minutes. We can use these durations to add or subtract them from date and time objects.

The TimeCategory provides an even Groovier way to work with durations. We can use constructs like 7.days + 12.minutes to create a duration. When we read this code it is just like reading English text. Here is some sample code:

import groovy.time.*

// Define period of 2 years, 3 months, 15 days, 0 hours, 23 minutes, 2 seconds and 0 milliseconds.
def period = new DatumDependentDuration(2, 3, 15, 0, 23, 2, 0)
assert '2 years, 3 months, 15 days, 23 minutes, 2.000 seconds' == period.toString()
def year2000 = new Date(100, 0, 0)  // Jan 1, 2000
assert 'Mon Apr 15 00:23:02 UTC 2002' == (period + year2000).toString()

// Define time period of 5 hours, 54 minutes and 30 milliseconds.
def time = new TimeDuration(5, 54, 0, 30)
assert '5 hours, 54 minutes, 0.030 seconds' == time.toString()

use (TimeCategory) {
    assert period.toString() == (2.years + 3.months + 15.days + 0.hour + 23.minutes + 2.seconds).toString()
    assert time.toString() == (5.hours + 54.minutes + 30.milliseconds).toString()

    // We can use period.from.now syntax.    
    def d1 = 1.week - 1.day
    def d2 = new Date() + 6.days
    assert d2.format('yyyy-MM-dd') == d1.from.now.format('yyyy-MM-dd')
    assert d2.clearTime() == d1.from.now
    
    // We can use period.ago syntax.
    def d3 = 3.days.ago
    def d4 = new Date() - 3
    assert d4.format('yyyy-MM-dd') == d3.format('yyyy-MM-dd')
    assert d4.clearTime() == d3
}

September 1, 2009

Groovy Goodness: Multiple Assignments

Since Groovy 1.6 we can define and assign values to several variables at once. This is especially useful when a method returns multiple values and we want to assign them to separate variables.

// Assign and declare variables.
def (username, email) = ['mrhaki', 'email@host.com']
assert 'mrhaki' == username
assert 'email@host.com' == email

// We can assign later than the definition of the variables.
int housenr
String streetname
(streetname, housenr) = ['Old Street', 42]
assert 42 == housenr
assert 'Old Street' == streetname

// We can also use type declarations.
def (String streetName, int houseNumber) = ['Old Street', 42]
assert 42 == houseNumber
assert 'Old Street' == streetName

// Return value of method can be assigned to multiple variables.
def iAmHere() {
    [29.20090, 12.90391]
}
def (coordX, coordY) = iAmHere()
assert coordX == 29.20090
assert coordY == 12.90391

// More values than variables: extra values are ignored.
def (a, b, c) = ['a', 'b', 'c', 'd']
assert 'a' == a
assert 'b' == b
assert 'c' == c

// Less values than variables: variable is not set.
def (x, y, z) = [100, 200]
assert 100 == x
assert 200 == y
assert !z

// Useful for getting regular expressions matching groups.
def money  = '12 Euro' 
def regexp = /(\d+) (\w+)/
def (exp, amount, currency) = (money =~ regexp)[0]
assert '12' == amount
assert 'Euro' == currency