Groovy

Introduction

Groovy

  • dynamic language for the Java Virtual Machine
  • based upon Java but with additional power features
  • inspired by Python, Ruby and Smalltalk
  • has modern programming features
  • supports Domain-Specific Languages
  • integrates with all existing Java classes and libraries
  • compiles straight to Java bytecodes

Groovy 1.8

Groovy 1.8 requires JDK 1.7

Java setup

  1. http://www.oracle.com/technetwork/java/javase/downloads/index.html
  2. Java SE Development Kit 7u21
  3. Create JAVA_HOME environment variable
  4. (Windows) Add %JAVA_HOME%\bin to PATH
  5. (GNU/Linux) Add $JAVA_HOME\bin to PATH

Groovy setup

  1. http://groovy.codehaus.org/Download
  2. Groovy 1.8.9
  3. Unzip to C:\groovy-1.8.9
  4. Create GROOVY_HOME environment variable
  5. (Windows) Add %GROOVY_HOME%\bin to PATH
  6. (GNU/Linux) Add $GROOVY_HOME\bin to PATH

Groovy Programs

  • (Shell) groovysh
  • (GUI) groovyConsole
  • (Interpreter) groovy script.groovy

External libraries

  • Put them in %GROOVY_HOME%\lib

First Groovy program


$ groovy -e "println 'Hello, world!'"
Hello, world!
          

Groovy Language

Comments


// until end of line
/* between delimiters */
/* with several
lines */
          

Strings


'Single quotes'

'''Triple
single
quotes'''

"Double quotes"

"""Triple
double
quotes"""
          

Printing


println "hello world!"  // hello world!
print 'hello world!\n'  // hello world!
println("hello world!") // hello world!
println("hello" + " " + "world" + "!") // hello world!
def a = 5
println "a number: ${a}, and a sum: ${1 + 3}" // a number: 5, and a sum: 4
          

Assignment


def a = 5
def b = 6.7
def c = 7, d = 8
int e = 9
String str = "10"
def str2 = "11"
          

Multiple assignment 1


def (x,y) = [1, 2]
println x   // 1
println y   // 2
def someFunction() {
  [ 1, 3, 5 ]
}
def (a, b, c) = someFunction()
println "${a} ${b} ${c}"  // 1, 3, 5
          

Multiple assignment 2


def firstName, lastName

(firstName, lastName) = "Miguel Cobá".tokenize()
println firstName   // Miguel
println lastName    // Cobá

def (a,b,c) = [1,2]
println "${a} ${b} ${c}" // 1 2 null
          

Parenthesis optional


println("Hello World!") // Hello World!
println "Hello World!"  // Hello World!
          

Safe navigation


def str = null
println str?.size() // null
str = "abc"
println str?.size() // 3
          

if-then-else


def a = 3
if (a > 2) {
  println "was true"
} else {
  println "was false"
}
          

Loops

					
def i = 10
while( i > 0 ) {
  println i--  // post-decrement
}

10.times { println "hello" }
          

Reflection


def a = "string"       
println a.class       // class java.lang.String
println String.name   // java.lang.String
println a.class.name  // java.lang.String
println a.class.fields 
println a.class.methods
          

Booleans


==
!=
>
>=
<
<=
          

Numbers

Integers

  • Integer
  • Long
  • BigInteger
  • Short
  • Byte

Examples


[110, 300000000000, 1000000000000000000000].each { println it.class }
println '42'.toInteger()        // 42
println Integer.parseInt("42")  // 42
          

Decimals

  • Float
  • Double
  • BigDecimal

Examples


[ 1.23e24, 4.56, 7.8E9, -1e-1].each { println it.class }
1.23e24.toString()
(-5.24566e-1234).abs() // 5.24566E-1234
          

Dates

Examples


def today = new Date()
def tomorrow = today + 1
def yesterday = today - 1
println today
println tomorrow
println yesterday
println today.after(yesterday)

def c1 = new GregorianCalendar(2010, Calendar.OCTOBER, 8)
def c2 = new GregorianCalendar(2010, Calendar.OCTOBER, 22)
println c1.after(c2)  // false
          

Collections

Lists 1


def list = [1, 2, 3, 4]
println list.get(2)         // 3
println list[2]             // 3
println list instanceof java.util.List  // true

def empty = []
println empty.size()        // 0
empty.add(10)
println empty.size()        // 1
          

Lists 2


def list = [ 1, 2 ,-4 , "hello", new Date()]
println list.size()   // 5
println list[0]       // 1
println list.first()  // 1
println list.last()   // Mon Jan 25 11:32:15 CDT 2010
list << "new value"
println list.last()   // new value

def list2 = [ 1, 2, 3 ]
list2 << [4, 5]
println list2        // [1, 2, 3, [4, 5]]
def list3 = list2.flatten()
println list3.size() // 4
println list3        // [1, 2, 3, 4, 5]
          

Operations 1


def items = ['one','two','three','four','five']
items.findAll { it.size() > 3 }   // [ 'three', 'four', 'five' ]
items.collect { it.capitalize() } // ['One','Two','Three','Four','Five']
items.each { println it } // prints each element
items.eachWithIndex { v, i -> 
  println "${i}: ${v}"
}
          

Operations 2

http://groovy.codehaus.org/groovy-jdk

  • findIndexOf
  • grep
  • any
  • every
  • min
  • max
  • flatten
  • intersect
  • sort
  • join

Start operator


['one', 'two', 'three']*.size() // [3, 3, 5]
          

Examples


def list = [1, 2, 2, 3]
println list - [2]    // [1, 3]
list.clear() 
println list          // []
list << 1
list << 2
println list.contains(2)  // true
println list.count(1)     // 1
list * 2                  // [1,2,1,2]
list.indexOf(1)           // 0
list.lastIndexOf(1)       // 2
println list.reverse()    // [2, 1, 2, 1]
list.removeAll(1)         // [2, 2]
list.unique()             // [2]
          

Array

Examples


def a = new Object[3]
println a.size()  // 3
println a.length  // 3
a[0] = 'a'
println a[0..1]   // ['a', null]
          

Maps

Maps

  • key/value store
  • keys are strings by default
  • use () to avoid conversion to string in keys

Examples 1


def map = [ "first":1, 2:"number two", "3": 3.0]
println map["first"]          // 1
println map.first             // 1
println map."2"               // null
println map[2]                // number two
println map[3]                // null
println map["3"]              // 3.0
println map."3"               // 3.0
map.fourth = "new value"     
println map.fourth            // new value
println map.class             // null
println map.getClass()        // java.util.LinkedHashMap
          

Examples 2


def map = [name: "Miguel",
          age: 31,
          date: new Date(),
          items: []]
println map.get("name") // Miguel
println map["name"]     // Miguel
println map.name        // Miguel
println map['items']    // []
println map instanceof java.util.Map  // true
          

Examples 3


def map = [:]
println map.size()  // 0
map.put("foo", 5)
println map.size()  // 1
println map.foo     // 5
          

Examples 4


def a = 5   
def map = [a:5, (a): 10]
println map["a"]      // 5
println map.a         // 5
println map[5]        // 10
println map[a]        // 10
map.foo = "new value"
println map.foo       // new value
          

Ranges

Ranges

  • java.lang.Comparable
  • next()/previous()

Inclusive ranges


def range = 5..8        // inclusive list: [5, 6, 7, 8]
println range.size()    // 4
println range.get(2)    // 7
println range[2]        // 7
println range instanceof java.util.List // true
println range.contains(5)    // true
println range.contains(8)    // true
println range.from           // 5
println range.to             // 8
          

Exclusive ranges


def range = 1..<4    // inclusive list: [1, 2, 3]
println range.size()    // 3
println range.get(2)    // 3
println range[2]        // 3
println range instanceof java.util.List    // true
println range.contains(1)    // true
println range.contains(4)    // false
println range.from           // 1
println range.to             // 3
          

Example 1


def range = 'a'..'c'
println range.size()      // 3
println range[2]          // 'c'
println range.from        // 'a'
println range.to          // 'c'
          

Example 2


for(i in 1..10) {
  println "Hello ${i}"
}

(1..10).each { println it }

def var
switch(age) {
  case 1..<18: var = "a"
  case 18..99: var = "b"
  default: var = "c"
}
          

Strings

Delimited by " and '


println "hello 'world'!"  // hello 'world'!
println 'hello "world"!'  // hello "world"!
          

Concatenation


def a = "world!"
println "hello" + world      // hello world!
          

Multi-line


def multiLineText = """hello\
world\
!
"""
println multiLineText   // hello world!
          

GString

  • $variable inside "-delimited strings
  • ${expression} inside "-delimited strings

Examples 1


def w = "world"
println "hello ${w}!"               // hello world!
println "hello $w!"                 // hello world!
println "today is: ${new Date()}"   // today is: Sun Oct 17 22:50:02 CDT 2010
          

Examples 2


def str = "2010-10-22"
def dateArray = str.split("-")
def year = dateArray[0].toInteger()
year = year + 1
println (year + "-" + dateArray[1] + "-" + dateArray[2])
println ([year, dateArray[1], dateArray[2]].join("-"))
dateArray[0] = (dateArray[0].toInteger() + 1).toString()
println (dateArray.join("-"))
println "Miguel".replace("igu","anu")
          

Regular expressions

regexp


==~ matches patterns
==  matches equality
//  delimiters for regexp
          

regexp 1


println "miguel" ==~ /miguel/
println "miguel" ==~ /mi...l/
println "miguel" ==~ /migu./
println "pattern" ==~ /patterns?/
println "patterns" ==~ /patterns?/
println "miguel" ==~ /m(igu|anu)el/
println "manuel" ==~ /m(igu|anu)el/
println "mel" ==~ /m(igu|anu)?el/
          

regexp 2


a?    0 or 1       

empty string or 'a'
          

regexp 3


a*    0 or more    

empty string, 'a', 'aa', 'aaa', 'aaaa', etc
          

regexp 4


a+    1 or more    

'a', 'aa', 'aaa', etc
          

regexp 5


a|b   a or b       

'a' or 'b' but not both


          

regexp 6


.     any single char 

'a', 'x', '1', '+', etc
          

regexp 7


[abcde]   any of a,b,c,d or e          

'a','b','c','d','e'
          

regexp 8


[1-3]    range, matches any of the char in the range   

'1', '2','3'
          

regexp 9


[^123]   any except 1, 2 or 3            

'4', 'r', '+'
          

regexp 10


(abc)    group an expression            

'abc'
          

regexp 11


^a       a at the beginning of line     

'a'
          

regexp 12


a$       a at the end of line           

'a'
          

matcher =~


def csv = "Coba, Miguel, 31, Groovy, Grails"
def regexp = 
/([a-zA-Z]+), ([a-zA-Z]+), ([0-9]+), ([a-zA-Z]+), ([a-zA-Z]+)/
def matcher = (csv =~ regexp)
if (matcher.matches()) {
  println(matcher.count)    // 1
  println(matcher[0])       
    // [Coba, Miguel, 31, Groovy, Grails]
  println(matcher[0][1])    // Cobá
  println(matcher[0][2])    // Miguel
  println(matcher[0][3])    // 31
  println(matcher[0][4])    // Groovy
  println(matcher[0][5])    // Grails
}
          

replacement


def str = "A string is always a string"
def matcher = (str =~ /string/)
str = matcher.replaceAll("number")
println (str)
          

Classes

Examples


class Counter {
  def num = 0
  def incr() { num++ }
  def decr() { num-- }
}
def c = new Counter()
c.incr()
println c.num             // 1
1000.times { c.decr() }
println c.num             // -999
          

Closures

Closures

Anonymous block of code that may

  • Take arguments
  • Return a value
  • Reference and use variables declared in its surrounding scope

Syntax

{ [arguments ->] statements }

  • [arguments ->]: optional comma-delimited list of arguments, typed or untyped
  • statements: 0 or more groovy statements

Closure semantics

Closures are anonymous

  • Can be referenced using untyped variables or typed variables of type Closure
  • Can be passed as method arguments and as arguments to other closures

Implicit method

  • Closures have one implicitly defined method, the one described by the arguments and body of the closure.
  • Implicit method name is doCall()
  • It is invoked by the call() method or the () syntax

Arguments 1

  • A closure has at least one argument, available as the implicit parameter *it* IF NO EXPLICIT parameters are defined.
  • Explicit arguments can be typed or untyped. When a parameter list is specified, the *it* variable is not available
  • They are checked at runtime, not at compile time

Arguments 2

  • If last argument is of type Object[], any excess arguments at invocation time are placed there

Example


def msgSum = { text, Object[] args ->
  def sum = 0
  args.each { sum += it }
  text + sum
}
println msgSum("The sum is:", 1, 2)
println msgSum("The sum is:", 1, 2, 4, 5)
          

Return value

Always return a value

  • one or more explicit return statements
  • value of the last executed statement if no explicit return
  • if the last statement has no value, null is returned

Example


def currencyConverter = { rate, value ->
  rate * value
}
def usdMxnConverter = currencyConverter.curry(13)
def eurMxnConverter = currencyConverter.curry(19)
println usdMxnConverter(5) // 5 USD -> 65 MXN
println eurMxnConverter(2) // 2 EUR -> 38 MXN
          

Example 2


def pr = { println it }
pr("hola mundo")      // hola mundo
pr(2)                 // 2
pr(new Date())        // Sun Oct 13 11:11:11 CDT 2010
          

Example 3


def square = { it * it }
println([1, 2, 3, 4].collect(square)) // [1, 4, 9, 16]
[1, 2, 3, 4].each(pr)                 // 1\n2\n3\n4\n
          

Example 4


def aValue = 3
def cl = { aValue * it }
println cl(4)                 // 12
println ([1, 2].collect(cl))  // [3, 6]
          

Example 5


def cl = { param -> param + 4 }
cl(6)     // 10
          

Example 6


def cl = { p1, p2 -> p1 * p2 }
println cl(3,4)         // 12
println cl("hola", 3)   // holaholahola 
          

Example 7


def l = [ 1, 2, 3, 4 ]
def sum = 0
l.each {
  sum += it
}
println "sum: ${sum}"
          

Example 8


def myFile = new File("file.txt") // file.txt is in current directory
printFileLine = { println "File line: " + it }
myFile.eachLine( printFileLine )
          

Groovy JDK

Groovy JDK

http://groovy.codehaus.org/groovy-jdk/

SQL

Simple query


import groovy.sql.Sql
def sql = Sql.newInstance(
        "jdbc:mysql://172.16.1.97/groovy",  // JDBC URL
        "groovy","groovy",                  // user, password
        "com.mysql.jdbc.Driver")            // JDBC Driver
sql.eachRow("select * from table", 
     { println "${it.id} ${it.aCol}" })
          

Groovy technical details

Default imports

  • java.io.*
  • java.lang.*
  • java.math.BigDecimal
  • java.math.BigInteger
  • java.net.*
  • java.util.*
  • groovy.lang.*
  • groovy.util.*

Assignment and equality


== equality operator
= assignment operator
is()
          

Reserved words


in
          

Arrays


def int[] a = [1,2,3]
          

Optional elements


semicolon (;)
return
          

Differences with Java

methods and classes are public by default

Exercise

Thanks!

Miguel Cobá

http://miguel.leugim.com.mx

Github: miguelcoba

miguel.coba@gmail.com