Wednesday, April 23, 2008

Groovy, groovy, groovy, groovy... (like Kaiser Chiefs)

Since some discussion has been done around groovy in the udig list lately, and since I traveled a lot by train lately, I found the time to dive into the Groovy language.

My God, did I like what I read!!
I will probably never script again in bash, whenever I am allowed to choose!!

And the fact that java and groovy can coexist!! And pointers on methods!! And... and... and...
Well, I wrote down some starter code for those that do not know groovy. Just to have a look.

So start the groovy, groovy, groovy, groovy song...



...and enjoy!!!


/*
* STRINGS MAGIC
*/
/*
* in groovy you don't have to define the type
*/
def string = "test string" // you don't need to put a semicolon at the end
println string
// want to quote a word? singlequote the whole and just do it
string = 'test "string"'
println string
// the resulting class is a java string
println string.class
println ""
println "*****************************************************"
println ""

/*
* heredocs, a great way to hold everything inside a string,
* without to care about quoting and xml slashes or brackets
*/
def xmlString = """inside here you can write whatever you want,
you can also embed xml with al its nasty characters:

can you imagine to do this in java?

"""
println xmlString
// and it is a java string!
println xmlString.class
println ""
println "*****************************************************"
println ""

/*
* so let's go one step further, introducing GStrings and using
* them together with heredocs to have fun
*/
def what = "whatever";
def question = "can you imagine to do this in java?";
def xmlGString = """inside here you can write ${what} you want,
you can also embed xml with al its nasty characters:

${question}

"""
println xmlGString;
// as you can see this time we have a groovy string implementation
println xmlGString.class;
println ""
println "*****************************************************"
println ""

/*
* LISTS MAGIC
*/
// define a list
def list = ["Merano","Bolzano","Trento"];
println list;
// defaults to ArrayList
println list.class;
// wanna cast? be dirty!
def listStringArray = ["Merano","Bolzano","Trento"] as String[];
println listStringArray;
println listStringArray.class;
def listSet = ["Merano","Bolzano","Trento"] as Set;
println listSet;
println listSet.class;
// add an element
list << "Lagundo"
println list;
println list.class;
// btw you can treat lists and arrays the same way!!
println list.get(0) + " is the same as " + list[0];
// find elements
println list.findAll{it.endsWith("ano")}
println ""
println "*****************************************************"
println ""

/*
* LOOPS MAGIC
*/
// forget about for loops, use closures
// with default variable 'it'...
list.each{println it}
// ...or with your variable...
list.each{myVar ->
println myVar
}
// ...or with an index and your variable
list.eachWithIndex{myVar, i ->
println "${i}: ${myVar}"
}
// sort...
list.sort();
println list
// and reverse sort
def revList = list.reverse();
// but note that while sort changes the original list,
// reverse makes a copy
println list
println revList
// concatenate list
def abc = ["a","b","c"]
def cde = ["c","d","e"]
def newabcde = abc + cde
println newabcde
// join the list to one single string
println newabcde.join(",")
println newabcde.join(" | ")
// max min and so on?
println abc.max()
println abc.min()
println abc.sum()
// modify each element of the list with collect
def newCollectedAbcde = newabcde.collect{
it += " is a letter"
}
newCollectedAbcde.each{println it}
// flatten nested lists
def newNestedList = ["a", "b", "c"]
newNestedList << cde
println newNestedList
println newNestedList.flatten()
// the spread-dot operator, execute mthods on every element
// this would not work: println abc.toUpperCase()
// whereas this will:
println abc*.toUpperCase()
println ""
println "*****************************************************"
println ""

/*
* MAPS MAGIC
*/
def townsProvinceMap = [merano:"BZ", bolzano:"BZ", trento:"TN"]
println townsProvinceMap
// defaults to linked hashmap
println townsProvinceMap.getClass()
// why I didn't use .class instead of getClass? Because of the way
// of getting values from the map:
println townsProvinceMap.merano
// therefor the following will give null
println townsProvinceMap.class
// add an element
townsProvinceMap.lagundo = "BZ"
println townsProvinceMap
// iterate the thing with the default value...
townsProvinceMap.each{println it}
// ...or with key and value separated...
townsProvinceMap.each{println "${it.key} is in province of ${it.value}"}
// ...or with own vars
townsProvinceMap.each{k, v ->
println "${k} is in province of ${v}"
}
println ""
println "*****************************************************"
println ""

/*
* RANGES MAGIC
*/
def range = 1..3
println range.class
// do some iterations
range.each{println it}
range.each{println "what?"}
// and what about dates?
def now = new Date();
def nextWeek = now + 7;
(now..nextWeek).each{
println it
}
// since ranges have a from, to and size...
println range.from
println range.to
println range.size()
// ...you can use them in for loops...
for (i in 1..3){ println "step number: ${i}"}
// ...which ovbiously could be done like the following
(1..3).each{ println "closure step number: ${it}"}
println ""
println "*****************************************************"
println ""

/*
* COMMAND LINE ARGUMENTS?
*/
if(args){
// this if checks both if args is != null and also not empty
println "supplied commandline args:"
args.each{println it}

} else {
println """
The commandline arguments part was not executed, since no argument was supplied.
"""
}
println ""
println "*****************************************************"
println ""

/*
* SYSTEM ENVIRONMENT
*/
System.env.each{ println it}
def userHome = System.getenv("HOME")
println userHome
println ""
println "*****************************************************"
println ""

/*
* FILES MAGIC
*/
// list a folder's content
def upperFolder = new File("..")
println "The contents of " + upperFolder.absolutePath + " are:"
upperFolder.eachFile{ file ->
println file
}
println "...of which folders:"
upperFolder.eachDir{ dir ->
println dir
}
println "...of which files:"
upperFolder.eachFile{ file ->
if(file.isFile())
println file
}
// recursive list content
println "Recursive folders content:"
upperFolder.eachDirRecurse{ dir ->
println dir
}
println ""
println "*****************************************************"
println ""

// read and write a file
// start with creating a new file to be read afterwards
def filePath = "./testFileToBeRemoved.txt"
def newFile = new File(filePath);
newFile.write("""A new header.
A new testline.
A second testline.
""")

// read the file and print the content
new File(filePath).eachLine{ println it }
// read the file into a string variable
def content = new File(filePath).text
println content
// append some content
def file = new File(filePath);
file << "Some text after the last line is appended!"
println file.text
// merge files
def file2 = new File(filePath + "2")
file2.write("Content of file 2");
println file2.text
def mergedFile = new File(filePath + "_merged")
mergedFile << file.text
mergedFile << file2.text
println "\nThe merged file:"
println mergedFile.text



And note that the above works as a compiled class as well as a command-line script!!

2 comments:

silli said...

Maybe to start with the coding we will install and configure the groovy development enviromnent... :-)

Here some hints...

To start with groovy:
Groovy installation
http://groovy.codehaus.org/Installing+Groovy

Groovy eclipse plugin
http://groovy.codehaus.org/Eclipse+Plugin

Silli

moovida said...

You might be right :) Thanks Silli!