16. Hello, world Legální java code, ale co vše je nadbytečné class Foo { public static void main(String[] args) { System.out.println("Hello, world"); } }
17. Hello, world Nadbytečné declarace obecných objektů Závorky, ukončení věty… System.out.println("Hello, world");
19. CLI Command Line Interface def cli = new CliBuilder(usage: 'showdate.groovy -[chflms] [date] [prefix]') cli.with {// Create the list of options. 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' } cli.p(argName:'heslo', longOpt:'password', args:1, required:true, type:GString, 'fill up the hic') def options = cli.parse(args) if (!options) return if ( options.h) { cli.usage() // 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 } GOP Groovy Option Parser Alternativa
20. PročGroovy? Dynamický skriptovací jazyk plus … JSR 241: Java standard Two-way contract: Groovy class je Java class: bytecode identita. Groovy and Java dědičnost tříd. Integrace s Java: annotations, generics, enums, familiar syntax. Groovy platforma je Java platforma: JSE library, debugging, ... Spring, Hibernate, web services, TestNG
21. Some Groovy language features Dynamically typed Closures Everything is an object. No primitives. == means equals. Really. Native syntax for lists, maps, regex Operator overriding Compact, expressive, readable
24. Ranges and regex Ranges (1..10).each { it -> println it } switch (age) { case 15..30: … } for (i in 1..10) { … } 'Hello, world'[2..4] == 'llo' Regex if ('rain' =~ /*ain/) println '"rain" does rhyme with "Spain"!'
25. Regex str = 'groovy.codehaus.org and www.aboutgroovy.com ‘ reNoWhiteSpace = /((?:(?![-_][-])+)+[A-Za-z][-]+)/ reWhiteSpace = /(?x)( (?: (?! [-_]) [-]+ )+ [A-Za-z] [-]+ ) / re = '''(?x) # to enable whitespace and comments ( # capture the hostname in $1 (?: # these parens for grouping only (?! [-_] ) # lookahead for neither underscore nor dash [w-] + # hostname component . # and the domain dot ) + # now repeat that whole thing a bunch of times [A-Za-z] # next must be a letter [w-] + # now trailing domain part ) # end of $1 capture ''' finder = str =~ re out = str (0..<finder.count).each{ adr = finder[it][0] out = out.replaceAll(adr, "$adr [${InetAddress.getByName(adr).hostAddress}]") } println out // => groovy.codehaus.org [63.246.7.187] and www.aboutgroovy.com [63.246.7.76]
26. Closures Metoda jako objekt Default argument “it” je volitelný. def squareIt = { return it * it } assert squareIt(5) == 25 10.times { println “I will not talk in class” } Variables visibility int x = 10 Closure addToX = { addThis -> x += addThis } addToX(2) assert x == 12
27. ClosuresStrategy pattern def multiplicationStrategies = [ { n, m -> n * m }, { n, m -> def result = 0; n.times{ result += m }; result } ] def sampleData = [ [3, 4, 12], [5, -5, -25] ] sampleData.each{ data -> multiplicationStrategies.each{ calc -> assert data[2] == calc(data[0], data[1]) } }
28. Operator overloading Override operators by overriding methods: a + b a.plus(b) a[b] a.getAt(b) a << b a.leftShift(b) switch (a) { case b: ... } b.isCase(a) a == b a.equals(b) a < b a.compareTo(b) < 0
29. Smart switch switch (x) {case 'James': println "yes it is me" breakcase 18..65: println "ok you are old" breakcase ~/Gw?+e/: println "your name starts with G and ends in e!" breakcase Date: println 'got a Date instance' breakcase ['John', 'Ringo', 'Paul', 'George']: println "Got one of the Beatles"breakdefault: println "Don't know $x“ }
30. Groovy convenience operators =~ regex find brandMatch = (line =~ /lt;bgt;([a-zA-Z]*)lt;brgt;/) if(brandMatch) brandName = brandMatch[0][1] ==~ regex match <=> spaceship, compareTo method of the Comparable interface ?:elvis ternary operator Java: name = name != null ? name : "default" Groovy: name = name ?: "default" ?. safe dereference. No worry about nulls. street = user?.address?.street * (spread) – “explode” the contents of a list or arraydef list = ['Groovy', 'Java‘]; assert ['Groovy', 'Java', 'Scala'] == [*list, 'Scala'] *. spread dot. Invoke on all items, return list. List result = invoice.lineItems*.total() parent*.action //equivalent to: parent.collect{ child -> child?.action }assert ['cat', 'elephant']*.size() == [3, 8]
31. GroovyBeans and JavaBeans // Groovy class MyBean { String item } MyBean b = new MyBean(item:‘foo’) String val = b.item b.item = ‘bar’ b[‘item’] = ‘bar’ // Java class MyBean { private String item; public String getItem() {…} public void setItem(…) {…} } MyBean b = new MyBean(); b.setItem(“foo”); String val = b.getItem(); b.setItem(“bar”)
32. Why brevity matters: Quicksort function sort(array) // pseudocode from Wikipedia var list less, greater if length(array) ≤ 1 return array select a pivot value pivot from array for each x in array if x < pivot then append x to less if x > pivot then append x to greater return concatenate(sort(less), pivot, sort(greater)) -------------------------------------------------------- def sort(list) { // Groovy implementation if (list.size() <= 1) return list def pivot = list[0] def less = list.findAll {it < pivot} def same = list.findAll {it == pivot} def greater = list.findAll {it > pivot} sort(less) + same + sort(greater) }
33. Quicksort in Java public static void qsort(Comparable[] c,int start,int end){ if(end <= start) return; Comparable comp = c[start]; int i = start,j = end + 1; for(;;){ do i++; while(i<end && c[i].compareTo(comp)<0); do j--; while(j>start && c[j].compareTo(comp)>0); if(j <= i) break; Comparable tmp = c[i]; c[i] = c[j]; c[j] = tmp; } c[start] = c[j]; c[j] = comp; qsort(c,start,j-1); qsort(c,j+1,end); } public static void qsort(Comparable[] c){ qsort(c,0,c.length-1); }
34. Object graph navigation: GPaths class Invoice { List items; … } class Item { Product product; int total() {…} … } class Product { String name; … } List<Invoice> invoices = …; // get all product names where item total > 7000 List result = invoices.items.grep{it.total() > 7000}.product.name // Java version: List result = new ArrayList(); for (Iterator<Invoice> i = invoices.iterator(); i.hasNext(); ) { List items = i.next().getItems(); for (Iterator j = items.iterator(); j.hasNext(); ) { Item item = (Item) j.next(); if (item.total() > 7000) result.add(item.getProduct().getName()); } }
36. Dynamic Groovy: categories // Dynamically add methods to any class class PersistenceCategory { static void save(Object o) { // save object } } use (PersistenceCategory) { // all objects now have save() method new MyBean().save() }
37. Dynamic Groovy: meta programming Change class/object behavior at runtime Meta-Object Protocol (MOP) You can intercept method calls and property accesses invokeMethod(...) getProperty(...) setProperty(...) etc String.metaClass.groovy << { Integer number -> delegate * number } << { String s -> delegate + s } << { -> delegate + ' Groovy rocks.' } assert 'GroovyGroovy' == 'Groovy'.groovy(2) assert 'Hello world from Groovy' == 'Hello world'.groovy(' from Groovy') assert 'It is true. Groovy rocks.' == 'It is true.'.groovy()
45. Grails ORM (GORM) class Book { String title String author Date releaseDate } book = Book.get(id) // let's change the title book.title = 'War and Peace' book.save() Book.listOrderByTitle() Book.findByReleaseDateBetween(startDate, endDate)
46. Files def file1 = new File('groovy1.txt') file1 << 'See how easy it is to add text to a file.‚ file1.withWriter('UTF-8') { writer -> writer.write('We can also use writers to add contents.‘)} sw = new StringWriter() file1.filterLine(sw) { it =~ /Groovy/ } assert 'Working with files the Groovy way is easy.' == sw.toString() files = [] new File('.').eachFileMatch(~/^groovy.*txt$/) { files << it.name } assert ['groovy1.txt', 'groovy2.txt', 'groovy3.txt'] == files files.each { new File(it).delete() }
47. Database def c = new ConfigSlurper().parse(new File('config.groovy').toURL()) def sql = groovy.sql.Sql.newInstance(c.db.schema, c.db.user, c.db.pwd, c.db.driver) sql.execute("CREATE TABLE tbl(oid integer,nam char(5))") def ds = sql.dataSet("tbl") new File(‘file.csv').splitEachLine(';') {ds.add(oid: it[0], name: it[1])} ds.each { println it} sql.eachRow("""select oid, name from tbl”””) {println “${it.name}} db{ config.groovy driver=denormalize("com.mysql.jdbc.Driver“) schema="jdbc:mysql://localhost/test" user="zen" pwd=“p" date = new Date() active = true } app{ //assert new Integer(20).equals(app.get("servers.setting2")); [1, 2, 3].each {this."setting${it}" = it * 10} } def normalize(s){return s.toUpperCase()}
48. Proč Groovy? Java is Groovy, Groovy is Java Standardizace Společný jazyk Architektura – Pseudocode Testování Automatizace Instalační a konfigurační skripty Builders, DSL Java Domain Grails, Spring, Seam
The Strategy Pattern allows you to abstract away particular algorithms from their usage. This allows you to easily swap the algorithm being used without having to change the calling code.