Loading...

Thursday, April 29, 2010

Groovy Goodness: Using the Subscript Operator on Iterators

Since Groovy 1.7.2 we can use the subscript operator for the Iterator class through the getAt() method. But we have to keep in mind the index value we use depends on a previous invocation of the subscript operator. Let's see this with an example:

def list = ['Groovy', 'Grails', 'Griffon', 'Gradle']
def iterator = list.iterator()

assert 'Groovy' == iterator[0]
assert 'Gradle' == iterator[-1]
assert !iterator[1]  // Iterator is exhausted.

iterator = list.iterator()  // Get new iterator.
def newList = []
(0..<list.size()).each {
 newList << iterator[0]  // Index 0 is next element.
}
assert 'Groovy,Grails,Griffon,Gradle' == newList.join(',')

Wednesday, April 28, 2010

Groovy Goodness: Traversing a Directory

Groovy adds the traverse() method to the File class in version 1.7.2. We can use this method to traverse a directory tree and invoke a closure to process the files and directories. If we look at the documentation we see we can also pass a map with a lot of possible options to influence the processing.

import static groovy.io.FileType.*
import static groovy.io.FileVisitResult.*

def groovySrcDir = new File(System.env['GROOVY_HOME'], 'src/')

def countFilesAndDirs = 0
groovySrcDir.traverse {
    countFilesAndDirs++
}
println "Total files and directories in ${groovySrcDir.name}: $countFilesAndDirs"

def totalFileSize = 0
def groovyFileCount = 0
def sumFileSize = { 
    totalFileSize += it.size()
    groovyFileCount++
}
def filterGroovyFiles = ~/.*\.groovy$/
groovySrcDir.traverse type: FILES, visit: sumFileSize, nameFilter: filterGroovyFiles
println "Total file size for $groovyFileCount Groovy source files is: $totalFileSize"

def countSmallFiles = 0
def postDirVisitor = {
    if (countSmallFiles > 0) {
     println "Found $countSmallFiles files with small filenames in ${it.name}"
 }
    countSmallFiles = 0
}
groovySrcDir.traverse(type: FILES, postDir: postDirVisitor, nameFilter: ~/.*\.groovy$/) {
    if (it.name.size() < 15) {
     countSmallFiles++
    }
}

Tuesday, April 27, 2010

Groovy Goodness: Working on Files or Directories (or Both) with FileType

Working with files in Groovy is very easy. We have a lot of useful methods available in the File class. For example we can run a Closure for each file that can be found in a directory with the eachFile() method. Since Groovy 1.7.1 we can define if we only want to process the directories, files or both. To do this we must pass a FileType constant to the method. See the following example code:

import groovy.io.FileType

// First create sample dirs and files.
(1..3).each { 
 new File("dir$it").mkdir() 
}
(1..3).each { 
 def file = new File("file$it")
 file << "Sample content for ${file.absolutePath}"
}

def currentDir = new File('.')
def dirs = []
currentDir.eachFile FileType.DIRECTORIES, {
    dirs << it.name
}
assert 'dir1,dir2,dir3' == dirs.join(',')

def files = []
currentDir.eachFile(FileType.FILES) {
    files << it.name
}
assert 'file1,file2,file3' == files.join(',')

def found = []
currentDir.eachFileMatch(FileType.ANY, ~/.*2/) {
   found << it.name
}

assert 'dir2,file2' == found.join(',')

Sunday, April 25, 2010

Groovy Goodness: Refactor XML Creation with StreamingMarkupBuilder

On Groovy's website we can find the article Using MarkupBuilder for Agile XML creation. Here we read how we create parts of the XML in separate methods, so we don't have to repeat ourselves if we are building XML. In this blog post we see a small example applying the same principles, but now we use StreamingMarkupBuilder. For the StreamingMarkupBuilder we must pass a closure to the bind() method. The closure contains a reference to the builder and we can use it in methods to define parts of the XML.

import groovy.xml.*

def markupBuilder = new StreamingMarkupBuilder()
def xml = markupBuilder.bind { builder ->
 client {
  name 'mrhaki'
  fullName 'Hubert A. Klein Ikkink'
  buildAddress builder, 'Main St.', 42, 'Ducktown'
  delivery {
      buildAddress builder, 'Main Av.', 101, 'Springfield'
      remarks 'During office hours'
  }
  buildItems builder
 }
}

def buildAddress(builder, streetName, number, city) {
 builder.address {
  street streetName
  houseNumber number
  buildCity builder, city
 }
}

def buildCity(builder, city) {
 builder.city city
}

def buildItems(builder) {
    builder.items {
     ['iPod', 'eBook'].eachWithIndex { product, index ->
      item(id: index + 1) {
       name "Item $product"
      }
     }
    }
}

assert '''<?xml version="1.0" encoding="UTF-8"?>
<client>
  <name>mrhaki</name>
  <fullName>Hubert A. Klein Ikkink</fullName>
  <address>
    <street>Main St.</street>
    <houseNumber>42</houseNumber>
    <city>Ducktown</city>
  </address>
  <delivery>
    <address>
      <street>Main Av.</street>
      <houseNumber>101</houseNumber>
      <city>Springfield</city>
    </address>
    <remarks>During office hours</remarks>
  </delivery>
  <items>
    <item id="1">
      <name>Item iPod</name>
    </item>
    <item id="2">
      <name>Item eBook</name>
    </item>
  </items>
</client>
''' == XmlUtil.serialize(xml)

Saturday, April 24, 2010

Groovy Goodness: Sum the Values in a Object Array

Since Groovy 1.7.1 we can use the sum() method on an array of objects. We already could use it for collections and iterators, but this has been extended to array of objects. The sum() can take a closure as an argument. The result of the closure is used to add the values together. Finally we can use an initial value for the sum.

def n = 0..5 as Integer[]

assert n instanceof Integer[]
assert      0 + 1 + 2 + 3 + 4 + 5 == n.sum()
assert 10 + 0 + 1 + 2 + 3 + 4 + 5 == n.sum(10)
assert      0 + 10 + 20 + 30 + 40 + 50 == n.sum { it * 10 }
assert 10 + 0 + 10 + 20 + 30 + 40 + 50 == n.sum(10, { it * 10 })

Friday, April 23, 2010

Groovy Goodness: Tokenize a String

Groovy adds the tokenize() method to the String class. We can use this method to split up a string value using a String, char or whitespace as delimiter. Groovy also adds a split() method without arguments that uses whitespace as delimiter, but returns a String array instead of List.

def s = 'one two three four'

def resultList = s.tokenize()
assert resultList.class.name == 'java.util.ArrayList'
assert ['one', 'two', 'three', 'four'] == resultList

def resultArray = s.split()
assert resultArray instanceof String[]
assert ['one', 'two', 'three', 'four'] == resultArray

def s1 = 'Java:Groovy'
assert ['Java', 'Groovy'] == s1.tokenize(":")
assert ['Java', 'Groovy'] == s1.tokenize(':' as char)

Thursday, April 22, 2010

Groovy Goodness: See if String is a Number

Groovy adds several methods to the String class we can use to determine if the String value can be parsed into a Number or related class like BigDecimal.

def n = '42.01'
def i = '201'

assert n.isNumber() && n.isBigDecimal() && n.isFloat() && n.isDouble()
assert i.isInteger() && i.isLong() && i.isBigInteger()

Wednesday, April 21, 2010

Groovy Goodness: Adding Maps to Map

Since Groovy 1.7.2 we can use the leftShift() method (<< operator) to add a map to another map.

def m = [name: 'Java', max: 10, sort: 'name']
def other = [name: 'Groovy', direction: 'asc']

m << other
assert [name: 'Groovy', max: 10, sort: 'name', direction: 'asc'] == m

Grails Goodness: Cleaning Before Running Tests

If we want to first clean our Grails project before we are running our test code we can pass the -clean argument. This way all source files will be recompiled so the tests are started from a clean slate.

$ grails test-app -clean

Tuesday, April 20, 2010

Groovy Goodness: Sorting a Map

Maps don't have an order for the elements, but we may want to sort the entries in the map. Since Groovy 1.7.2 we can use the sort() method which uses the natural ordering of the keys to sort the entries. Or we can pass a Comparator to the sort() method to define our own sorting algorithm for the keys.

def m = [sort: 'asc', name: 'test', paginate: true, max: 100]

def expectedKeys = ['max', 'name', 'paginate', 'sort'] 
assert expectedKeys == m.sort()*.key  // Since 1.7.2
assert expectedKeys == m.sort( { k1, k2 -> k1 <=> k2 } as Comparator )*.key // Since 1.7.2

// Sorting before Groovy 1.7.2
assert expectedKeys == new TreeMap(m)*.key
assert expectedKeys == m.sort { e1, e2 -> e1.key <=> e2.key }*.key  // Sort by closure.

Monday, April 19, 2010

Groovy Goodness: New Ways to Curry

A couple of weeks ago I gave a presentation about Groovy and the subject of closures and the curry() method was covered. Someone from the audience asked if the arguments could be 'curried' from right to left instead of from left to right. I had to say no, but since Groovy 1.7.2 this isn't true anymore. Groovy 1.7.2 adds the rcurry() method which uses a right to left order. And as a bonus we also have got the ncurry() method where we can supply a parameter value for an argument of the closure at a specific index.

@Grab('commons-lang:commons-lang:2.5')
import org.apache.commons.lang.RandomStringUtils as RSU

def randomClosure = { size, letters, numbers ->
    // Invoke RandomStringUtils.random() method 
    RSU.random size, letters, numbers
}

def randomNumbers = randomClosure.rcurry(false, true)  // letters = false, numbers = true
def randomLetters = randomClosure.ncurry(1, true, false) // letters = true, numbers = false

println randomClosure(10, true, true)  // Sample output: VG7mffNAdA
println randomNumbers(10)              // Sample output: 8099670444
println randomLetters(10)              // Sample output: ZOHlHewEPU

Sunday, April 18, 2010

Groovy Goodness: Configuring Grape to Use Classloader

Groovy has Grape to define dependencies which are necessary for our code to be downloaded by Ivy. This way we don't have to distribute third-party libraries with our code, but we only have to define the dependencies in our code. We can define these dependencies with the @Grab annotations. If we want to define multiple @Grab annotation we can group them together within a @Grapes annotation.

By default the dependencies are available in the same classloader as our Groovy script or application. But sometimes this is not enough. For example if we have a script with a dependency on a SQL database driver and in our code java.sql.DriverManager.getConnection() is used we want our driver class to be on the system classloader. That is because the DriverManager class only can 'see' classes in the system classloader and not other classloaders. A possible exception we get is java.sql.SQLException: No suitable driver found.

To support this scenario we add the @GrabConfig annotation and define that the dependency is part of the system classloader. And we are ready to use the dependency in our script.

@Grapes([
 @Grab('org.slf4j:slf4j-simple:1.5.11'),
 @Grab('mysql:mysql-connector-java:5.1.12'),
 @GrabConfig(systemClassLoader = true)
])
import org.slf4j.*
import groovy.sql.*

def logger = LoggerFactory.getLogger('sql')

logger.info 'Initialize SQL'

def username = args[0]  // First argument passed to script.
def password = args[1]  // Second argument passed to script is password.
def sql = Sql.newInstance('jdbc:mysql://localhost/test', username, password, 'com.mysql.jdbc.Driver')

logger.info "Got myself a SQL connection: $sql"

Thursday, April 15, 2010

Grails Goodness: Invoking a Single Test Method

When we use $ grails test-app to test our code all tests are run. We can specify a single test class as an argument for the test-app script. So for example if we have a HelloWorldControllerTests class we use the following command $ grails test-app HelloWorldController. Grails supports wildcards for defining the test class, so we can also use $ grails test-app Hello* for example.

But we can even specify the method in our HelloWorldControllerTests class we want to be tested. If the test class has the method testSayHello() we use the following command $ grails test-app HelloWorldController.sayHello and only the testSayHello().