SlideShare une entreprise Scribd logo
1  sur  104
Télécharger pour lire hors ligne
Submission 631 © ASERT 2007




                              Groovy Tutorial
                                  Dr Paul King
                                ASERT, Australia




                                                   Agile 2007 - 1
Topics
                              Introduction
                              •   Language Basics
                              •   Closures
                              •   Builders
                              •
Submission 631 © ASERT 2007




                                  Data Access
                              •   Other Features
                              •   Testing with Groovy
                              •   Further Integration
                              •   Grails
                              •   More Information


                                                                 Agile 2007 - 2
What is Groovy?
                              • “Groovy is like a super version
                                of Java. It can leverage Java's
                                enterprise capabilities but also
                                has cool productivity features like closures,
Submission 631 © ASERT 2007




                                DSL support, builders and dynamic typing.”

                               Groovy = Java –   boiler plate code
                                             +   optional dynamic typing
                                             +   closures
                                             +   domain specific languages
                                             +   builders
                                             +   metaprogramming
                                                                           Agile 2007 - 3
Groovy Goodies Overview
                              • Fully object oriented
                              • Closures: reusable
                                and assignable
                                pieces of code
                              • Operators can be          • GPath: efficient
Submission 631 © ASERT 2007




                                overloaded                  object navigation
                              • Multimethods              • GroovyBeans
                              • Literal declaration for   • grep and switch
                                lists (arrays), maps,
                                                          • Templates, builder,
                                ranges and regular
                                                            swing, Ant, markup,
                                expressions
                                                            XML, SQL, XML-RPC,
                                                            Scriptom, Grails,
                                                            tests, Mocks   Agile 2007 - 4
Growing Acceptance
                              • A slow and steady start but now
                                gaining in momentum; growing in
                                maturity & mindshare
Submission 631 © ASERT 2007




                                                                  Groovy
                                                                  Recipes


                                                                  Pragmatic
                                                                  Bookshelf

                                                                    Agile 2007 - 5
The Landscape of JVM Languages

                                                                                                                    optional
                                                                                                                       static
                                                                                                                       types
Submission 631 © ASERT 2007




                                                Dynamic features call
                                                for dynamic types                                  Java bytecode calls
                                                                                                       for static types




                              The terms “Java Virtual Machine” and “JVM” mean a Virtual Machine for the Java™ platform.
                                                                                                                           Agile 2007 - 6
Groovy Starter
                              System.out.println(quot;Hello, World!quot;);   // optional semicolon,
                              println 'Hello, World!'                // System.out, brackets,
                                                                     // main() method

                              def name = 'Guillaume'                 // dynamic typing
                              println quot;$name, I'll get the car.quot;     // GString

                              String longer = quot;quot;quot;${name}, the car
Submission 631 © ASERT 2007




                              is in the next row.quot;quot;quot;                 // multi-line string
                                                                     // with static typing

                              assert 0.5 == 1/2                      // BigDecimal equals()

                              def printSize(obj) {                   // optional duck typing
                                  print obj?.size()                  // safe dereferencing
                              }

                              def animals = ['ant', 'bee', 'cat']    // native list syntax
                              assert animals.every { pet ->          // closure support
                                  pet < 'dog'                        // overloading
                              }
                                                                                              Agile 2007 - 7
A Better Java...
                              import java.util.List;
                              import java.util.ArrayList;

                              class Erase {
                                                                                               This code
                                  private List filterLongerThan(List strings, int length) {
                                      List result = new ArrayList();
                                                                                                 is valid
                                      for (int i = 0; i < strings.size(); i++) {
                                                                                               Java and
                                          String s = (String) strings.get(i);
                                          if (s.length() <= length) {
                                                                                              valid Groovy
                                              result.add(s);
Submission 631 © ASERT 2007




                                          }
                                      }
                                      return result;
                                  }
                                  public static void main(String[] args) {
                                      List names = new ArrayList();
                                      names.add(quot;Tedquot;); names.add(quot;Fredquot;);
                                      names.add(quot;Jedquot;); names.add(quot;Nedquot;);
                                                                                               Based on an
                                      System.out.println(names);
                                                                                               example by
                                      Erase e = new Erase();
                                      List shortNames = e.filterLongerThan(names, 3);          Jim Weirich
                                      System.out.println(shortNames.size());
                                                                                               & Ted Leung
                                      for (int i = 0; i < shortNames.size(); i++) {
                                          String s = (String) shortNames.get(i);
                                          System.out.println(s);
                                      }
                                  }
                              }
                                                                                                     Agile 2007 - 8
...A Better Java...
                              import java.util.List;
                              import java.util.ArrayList;

                              class Erase {
                                                                                                   Do the
                                  private List filterLongerThan(List strings, int length) {
                                      List result = new ArrayList();
                                                                                                semicolons
                                      for (int i = 0; i < strings.size(); i++) {
                                                                                               add anything?
                                          String s = (String) strings.get(i);
                                          if (s.length() <= length) {
                                                                                               And shouldn’t
                                              result.add(s);
Submission 631 © ASERT 2007




                                          }
                                                                                                we us more
                                      }
                                                                                                modern list
                                      return result;
                                  }
                                                                                                 notation?
                                  public static void main(String[] args) {
                                      List names = new ArrayList();
                                                                                                  Why not
                                      names.add(quot;Tedquot;); names.add(quot;Fredquot;);
                                      names.add(quot;Jedquot;); names.add(quot;Nedquot;);
                                                                                              import common
                                      System.out.println(names);
                                                                                                 libraries?
                                      Erase e = new Erase();
                                      List shortNames = e.filterLongerThan(names, 3);
                                      System.out.println(shortNames.size());
                                      for (int i = 0; i < shortNames.size(); i++) {
                                          String s = (String) shortNames.get(i);
                                          System.out.println(s);
                                      }
                                  }
                              }
                                                                                                      Agile 2007 - 9
...A Better Java...
                              class Erase {
                                  private List filterLongerThan(List strings, int length) {
                                      List result = new ArrayList()
                                      for (String s in strings) {
                                          if (s.length() <= length) {
                                              result.add(s)
                                          }
                                      }
                                      return result
                                  }
Submission 631 © ASERT 2007




                                  public static void main(String[] args) {
                                      List names = new ArrayList()
                                      names.add(quot;Tedquot;); names.add(quot;Fredquot;)
                                      names.add(quot;Jedquot;); names.add(quot;Nedquot;)
                                      System.out.println(names)
                                      Erase e = new Erase()
                                      List shortNames = e.filterLongerThan(names, 3)
                                      System.out.println(shortNames.size())
                                      for (String s in shortNames) {
                                          System.out.println(s)
                                      }
                                  }
                              }




                                                                                              Agile 2007 - 10
...A Better Java...
                              class Erase {
                                  private List filterLongerThan(List strings, int length) {
                                      List result = new ArrayList()
                                      for (String s in strings) {
                                          if (s.length() <= length) {
                                                                                                Do we need
                                              result.add(s)
                                                                                              the static types?
                                          }
                                      }
                                                                                              Must we always
                                      return result
                                  }
                                                                                                have a main
Submission 631 © ASERT 2007




                                                                                                 method and
                                  public static void main(String[] args) {
                                      List names = new ArrayList()
                                                                                              class definition?
                                      names.add(quot;Tedquot;); names.add(quot;Fredquot;)
                                      names.add(quot;Jedquot;); names.add(quot;Nedquot;)
                                                                                                 How about
                                      System.out.println(names)
                                      Erase e = new Erase()
                                                                                                  improved
                                      List shortNames = e.filterLongerThan(names, 3)
                                                                                                consistency?
                                      System.out.println(shortNames.size())
                                      for (String s in shortNames) {
                                          System.out.println(s)
                                      }
                                  }
                              }




                                                                                                       Agile 2007 - 11
...A Better Java...
                              def filterLongerThan(strings, length) {
                                  def result = new ArrayList()
                                  for (s in strings) {
                                      if (s.size() <= length) {
                                          result.add(s)
                                      }
                                  }
                                  return result
Submission 631 © ASERT 2007




                              }

                              names = new ArrayList()
                              names.add(quot;Tedquot;)
                              names.add(quot;Fredquot;)
                              names.add(quot;Jedquot;)
                              names.add(quot;Nedquot;)
                              System.out.println(names)
                              shortNames = filterLongerThan(names, 3)
                              System.out.println(shortNames.size())
                              for (s in shortNames) {
                                  System.out.println(s)
                              }



                                                                        Agile 2007 - 12
...A Better Java...
                              def filterLongerThan(strings, length) {
                                  def result = new ArrayList()
                                  for (s in strings) {
                                      if (s.size() <= length) {
                                                                           Shouldn’t we
                                          result.add(s)
                                      }
                                                                           have special
                                  }
                                                                        notation for lists?
                                  return result
Submission 631 © ASERT 2007




                              }
                                                                            And special
                                                                            facilities for
                              names = new ArrayList()
                              names.add(quot;Tedquot;)
                                                                         list processing?
                              names.add(quot;Fredquot;)
                              names.add(quot;Jedquot;)
                              names.add(quot;Nedquot;)
                              System.out.println(names)
                              shortNames = filterLongerThan(names, 3)
                              System.out.println(shortNames.size())
                              for (s in shortNames) {
                                  System.out.println(s)
                              }



                                                                                      Agile 2007 - 13
...A Better Java...
                              def filterLongerThan(strings, length) {
                                  return strings.findAll{ it.size() <= length }
                              }

                              names = [quot;Tedquot;, quot;Fredquot;, quot;Jedquot;, quot;Nedquot;]
                              System.out.println(names)
                              shortNames = filterLongerThan(names, 3)
                              System.out.println(shortNames.size())
Submission 631 © ASERT 2007




                              shortNames.each{ System.out.println(s) }




                                                                                  Agile 2007 - 14
...A Better Java...
                              def filterLongerThan(strings, length) {
                                  return strings.findAll{ it.size() <= length }
                              }
                                                                                   Is the method
                                                                                   now needed?
                              names = [quot;Tedquot;, quot;Fredquot;, quot;Jedquot;, quot;Nedquot;]
                              System.out.println(names)
                                                                                  Easier ways to
                              shortNames = filterLongerThan(names, 3)
                                                                                    use common
                              System.out.println(shortNames.size())
Submission 631 © ASERT 2007




                              shortNames.each{ System.out.println(s) }
                                                                                     methods?
                                                                                    Are brackets
                                                                                  required here?




                                                                                          Agile 2007 - 15
...A Better Java...
                              names = [quot;Tedquot;, quot;Fredquot;, quot;Jedquot;, quot;Nedquot;]
                              println names
                              shortNames = names.findAll{ it.size() <= 3 }
                              println shortNames.size()
                              shortNames.each{ println it }
Submission 631 © ASERT 2007




                              [quot;Tedquot;, quot;Fredquot;, quot;Jedquot;, quot;Nedquot;]
                              3
                              Ted
                              Jed
                              Ned




                                                                         Agile 2007 - 16
...A Better Java
                              names = [quot;Tedquot;, quot;Fredquot;, quot;Jedquot;, quot;Nedquot;]
                              println names
                              shortNames = names.findAll{ it.size() <= 3 }
                              println shortNames.size()
                              shortNames.each{ println it }
                                    import java.util.List;
Submission 631 © ASERT 2007




                                    import java.util.ArrayList;

                                    class Erase {
                                        private List filterLongerThan(List strings, int length) {
                                            List result = new ArrayList();
                                            for (int i = 0; i < strings.size(); i++) {
                                                String s = (String) strings.get(i);
                                                if (s.length() <= length) {
                                                    result.add(s);
                                                }
                                            }
                                            return result;
                                        }
                                        public static void main(String[] args) {
                                            List names = new ArrayList();
                                            names.add(quot;Tedquot;); names.add(quot;Fredquot;);
                                            names.add(quot;Jedquot;); names.add(quot;Nedquot;);
                                            System.out.println(names);
                                            Erase e = new Erase();
                                            List shortNames = e.filterLongerThan(names, 3);
                                            System.out.println(shortNames.size());
                                            for (int i = 0; i < shortNames.size(); i++) {
                                                String s = (String) shortNames.get(i);
                                                System.out.println(s);
                                            }
                                        }
                                    }
                                                                                                    Agile 2007 - 17
Better JavaBeans...
                              import java.math.BigDecimal;                                           ...

                              public class BikeJavaBean {                                            public void setModel(String model) {
                                  private String manufacturer;                                           this.model = model;
                                  private String model;                                              }
                                  private int frame;
                                  private String serialNo;                                           public int getFrame() {
                                  private double weight;                                                 return frame;
                                  private String status;                                             }
                                  private BigDecimal cost;
                                                                                                     public String getSerialNo() {
                                 public BikeJavaBean(String manufacturer, String model,                  return serialNo;
                                                     int frame, String serialNo,                     }
                                                     double weight, String status) {
                                     this.manufacturer = manufacturer;                               public void setSerialNo(String serialNo) {
                                     this.model = model;                                                 this.serialNo = serialNo;
Submission 631 © ASERT 2007




                                     this.frame = frame;                                             }
                                     this.serialNo = serialNo;
                                     this.weight = weight;                                           public double getWeight() {
                                     this.status = status;                                               return weight;
                                 }                                                                   }

                                 public String toString() {                                          public void setWeight(double weight) {
                                     return quot;Bike:‚ +                                                    this.weight = weight;
                                             ‚n    manufacturer   --   quot;   +   manufacturer +       }
                                             quot;n    model          --   quot;   +   model +
                                             quot;n    frame          --   quot;   +   frame +              public String getStatus() {
                                             quot;n    serialNo       --   quot;   +   serialNo +               return status;
                                             quot;nquot;;                                                   }
                                 }
                                                                                                     public void setStatus(String status) {
                                 public String getManufacturer() {                                       this.status = status;
                                     return manufacturer;                                            }
                                 }
                                                                                                     public BigDecimal getCost() {
                                 public void setManufacturer(String manufacturer) {                      return cost;
                                     this.manufacturer = manufacturer;                               }
                                 }
                                                                                                     public void setCost(BigDecimal cost) {
                                 public String getModel() {                                              this.cost = cost.setScale(3, BigDecimal.ROUND_HALF_UP);
                                     return model;                                                   }
                                 }                                                               }
                                 ...

                              Modified example from: http://www.ibm.com/developerworks/library/j-pg09196.html                                             Agile 2007 - 18
...Better JavaBeans...
                              import java.math.BigDecimal;                                           ...
                                                                                                                                                       Auto
                              public class BikeJavaBean {                                            public void setModel(String model) {
                                  private String manufacturer;                                           this.model = model;
                                                                                                                                                   getters?
                                  private String model;                                              }
                                  private int frame;

                                                                                                                                                       Auto
                                  private String serialNo;                                           public int getFrame() {
                                  private double weight;                                                 return frame;
                                  private String status;                                             }
                                                                                                                                                   setters?
                                  private BigDecimal cost;
                                                                                                     public String getSerialNo() {
                                 public BikeJavaBean(String manufacturer, String model,                  return serialNo;
                                                                                                                                                       Auto
                                                     int frame, String serialNo,                     }
                                                     double weight, String status) {

                                                                                                                                              construction?
                                     this.manufacturer = manufacturer;                               public void setSerialNo(String serialNo) {
                                     this.model = model;                                                 this.serialNo = serialNo;
Submission 631 © ASERT 2007




                                     this.frame = frame;                                             }
                                     this.serialNo = serialNo;
                                     this.weight = weight;                                           public double getWeight() {
                                     this.status = status;                                               return weight;
                                 }                                                                   }

                                 public String toString() {                                          public void setWeight(double weight) {
                                     return quot;Bike:‚ +                                                    this.weight = weight;
                                             ‚n    manufacturer   --   quot;   +   manufacturer +       }
                                             quot;n    model          --   quot;   +   model +
                                             quot;n    frame          --   quot;   +   frame +              public String getStatus() {
                                             quot;n    serialNo       --   quot;   +   serialNo +               return status;
                                             quot;nquot;;                                                   }
                                 }
                                                                                                     public void setStatus(String status) {
                                 public String getManufacturer() {                                       this.status = status;
                                     return manufacturer;                                            }
                                 }
                                                                                                     public BigDecimal getCost() {
                                 public void setManufacturer(String manufacturer) {                      return cost;
                                     this.manufacturer = manufacturer;                               }
                                 }
                                                                                                     public void setCost(BigDecimal cost) {
                                 public String getModel() {                                              this.cost = cost.setScale(3, BigDecimal.ROUND_HALF_UP);
                                     return model;                                                   }
                                 }                                                               }
                                 ...

                                                                                                                                                          Agile 2007 - 19
... Better JavaBeans
                              class BikeGroovyBean {
                                  String manufacturer, model, serialNo, status
                                  final Integer frame
                                  Double weight
                                  BigDecimal cost

                                    public void setCost(BigDecimal newCost) {
Submission 631 © ASERT 2007




                                        cost = newCost.setScale(3, BigDecimal.ROUND_HALF_UP)
                                    }

                                    public String toString() {
                                        return quot;quot;quot;Bike:
                                    manufacturer -- $manufacturer
                                    model        -- $model
                                    frame        -- $frame
                                    serialNo     -- $serialNo
                              quot;quot;quot;
                                    }
                              }
                                                                                      Agile 2007 - 20
Topics
                              • Introduction
                              Language Basics
                              • Closures
                              • Builders
Submission 631 © ASERT 2007




                              • Data Access
                              • Other Features
                              • Testing with Groovy
                              • Further Integration
                              • Grails
                              • More Information
                                                          Agile 2007 - 21
Strings…
                              • Several forms
                                – Single quotes for     // normal strings
                                  simple strings        def firstname = 'Kate'
                                                        def surname= quot;Bushquot;
                                – Double quotes for     assert firstname * 2 == 'KateKate'
                                  GStrings which
                                                        // GString
                                  support variable
Submission 631 © ASERT 2007




                                                        def fullname = quot;$firstname $surnamequot;
                                  expansion             assert fullname == 'Kate Bush'
                                – Slashy strings        assert fullname - firstname == ' Bush'
                                                        assert fullname.padLeft(10) ==
                                  behave like                                     ' Kate Bush'
                                  GStrings but
                                                        // indexing (including ranges)
                                  preserve
                                                        assert fullname[0..3] == firstname
                                  backslashes (great    assert fullname[-4..-1] == surname
                                  for regex and         assert fullname[5, 3..1] == 'Beta'
                                  directory names)
                                – Multi-line versions
                                                                                      Agile 2007 - 22
…Strings…
                                                           // slashy string: (almost) no escaping
                              // Multi-line strings        def path = /C:WindowsSystem32/
                              def twister = '''
                              She sells, sea shells        def plain = 'nrtbf$'
                              By the sea shore'''          assert plain.size() == 7
                                                           def slashy = /nrtbf$/
                              def lines =                  assert slashy.size() == 14
                                  twister.split('n')
Submission 631 © ASERT 2007




                              assert lines.size() == 2     // late binding trick with closures
                                                           fullname = quot;${-> firstname} $surnamequot;
                              def address = quot;quot;quot;            assert fullname == 'Kate Bush'
                              $fullname                    firstname = 'George'
                              123 First Ave                surname = 'Clooney'
                              New York                     assert fullname == 'George Bush'
                              quot;quot;quot;.trim()
                                                           println quot;quot;quot;
                              def lines =                   ----------------------
                                  address.split('n')      |    $fullname        |
                              assert lines.size() == 3     |    123 First Ave    |
                                                           |    New York         |
                                                            ----------------------
                                                           quot;quot;quot;
                                                                                           Agile 2007 - 23
…Strings
                              // more substrings
                              string = 'hippopotamus'
                              assert string - 'hippo' - 'mus' + 'to' == 'potato'
                              assert string.replace('ppopotam','bisc') == 'hibiscus'

                              // processing characters
                              assert 'apple'.toList() == ['a', 'p', 'p', 'l', 'e']
                              //also: 'apple' as String[], 'apple'.split(''), 'apple'.each{}
Submission 631 © ASERT 2007




                              string = quot;an apple a dayquot;
                              assert string.toList().unique().sort().join() == ' adelnpy'

                              // reversing chars/words
                              assert 'string'.reverse() == 'gnirts'

                              string = 'Yoda said, quot;can you see this?quot;'
                              revwords = string.split(' ').toList().reverse().join(' ')
                              assert revwords == 'this?quot; see you quot;can said, Yoda'

                              words = ['bob', 'alpha', 'rotator', 'omega', 'reviver']
                              bigPalindromes = words.findAll{w -> w == w.reverse() && w.size() > 5}
                              assert bigPalindromes == ['rotator', 'reviver']
                                                                                           Agile 2007 - 24
Numbers...
                              • Java Approach
                                – Supports primitive types and object types
                                – Has wrapper classes to allow conversion
                                – Java 5+ has autoboxing to hide difference
                              • Groovy Approach
Submission 631 © ASERT 2007




                                – Treats everything as an object at the language level
                                   • And does appropriate autoboxing under the covers when
                                     integrating with Java
                                – BigDecimal used as the default type for non-Integers
                                – Operator overloading applies to all common
                                  operations on numbers, e.g. 3 * 4 is the same as
                                  3.multiply(4)
                                   • You can use these operators for your own types, e.g. Person
                                     * 3 calls the multiple method on your person object
                                                                                         Agile 2007 - 25
...Numbers
                              def x = 3
                              def y = 4
                              assert x + y == 7
                              assert x.plus(y) == 7
                              assert x instanceof Integer

                              assert 0.5 == 1/2   // uses BigDecimal arithmetic as default
                              def a = 2 / 3       // 0.6666666666
                              def b = a.setScale(3, BigDecimal.ROUND_HALF_UP)
                              assert b.toString() == '0.667'
Submission 631 © ASERT 2007




                              assert   4 + 3 == 7                //   4.plus(3)
                              assert   4 - 3 == 1                //   4.minus(3)
                              assert   4 * 3 == 12               //   4.multiply(12)
                              assert   4 % 3 == 1                //   4.mod(3)
                              assert   4 ** 3 == 64              //   4.power(3)
                              assert   4 / 3 == 1.3333333333     //   4.div(3)
                              assert   4.intdiv(3) == 1          //   normal integer division

                              assert   !(4 == 3)      //   !(4.equals(3))
                              assert   4 != 3         //   ! 4.equals(3)
                              assert   !(4 < 3)       //   4.compareTo(3)   <0
                              assert   !(4 <= 3)      //   4.compareTo(3)   <= 0
                              assert   4>3            //   4.compareTo(3)   >0
                              assert   4 >= 3         //   4.compareTo(3)   >= 0
                              assert   4 <=> 3 == 1   //   4.compareTo(3)                       Agile 2007 - 26
Dates...
                              • Mostly same support as Java
                              • Use java.util.Date or java.util.Calendar
                                – Or java.sql.Date etc.
                                – Can use static imports to help
                              • Or 3rd party package like Joda Time
Submission 631 © ASERT 2007




                              • Does have special support for changing
                                times:
                                date2 = date1 + 1.week – 3.days + 6.hours
                              • More utility methods expected for
                                inputting and outputting dates
                              • Potentially will change with JSR 310
                                                                            Agile 2007 - 27
...Dates
                              import static java.util.Calendar.getInstance as now
                              import org.codehaus.groovy.runtime.TimeCategory
                              import java.text.SimpleDateFormat

                              println now().time             Thu Jun 28 10:10:34 EST 2007
                                                             Fri Jun 29 10:10:35 EST 2007
                              def date = new Date() + 1      Tue Jul 17 11:10:35 EST 2007
Submission 631 © ASERT 2007




                              println date                   Date was Jun/03/1998

                              use(TimeCategory) {
                                  println new Date() + 1.hour + 3.weeks - 2.days
                              }

                              input = quot;1998-06-03quot;
                              df1 = new SimpleDateFormat(quot;yyyy-MM-ddquot;)
                              date = df1.parse(input)
                              df2 = new SimpleDateFormat(quot;MMM/dd/yyyyquot;)
                              println 'Date was ' + df2.format(date)

                                                                                    Agile 2007 - 28
Lists, Maps, Ranges
                              • Lists
                                – Special syntax for list literals
                                – Additional common methods (operator overloading)
                                        def list = [3, new Date(), 'Jan']
                                        assert list + list == list * 2
Submission 631 © ASERT 2007




                              • Maps
                                – Special syntax for map literals
                                – Additional common methods
                                        def map = [a: 1, b: 2]
                                        assert map['a'] == 1 && map.b == 2

                              • Ranges
                                – Special syntax for various kinds of ranges
                                        def letters = 'a'..'z'
                                        def numbers = 0..<10
                                                                               Agile 2007 - 29
Lists
                              assert   [1,2,3,4]           == (1..4)
                              assert   [1,2,3] + [1]       == [1,2,3,1]
                              assert   [1,2,3] << 1        == [1,2,3,1]
                              assert   [1,2,3,1] - [1]     == [2,3]
                              assert   [1,2,3] * 2         == [1,2,3,1,2,3]
                              assert   [1,[2,3]].flatten() == [1,2,3]
                              assert   [1,2,3].reverse()   == [3,2,1]
Submission 631 © ASERT 2007




                              assert   [1,2,3].disjoint([4,5,6])
                              assert   [1,2,3].intersect([4,3,1]) == [3,1]
                              assert   [1,2,3].collect{ it+3 }    == [4,5,6]
                              assert   [1,2,3,1].unique().size() == 3
                              assert   [1,2,3,1].count(1) == 2
                              assert   [1,2,3,4].min()     == 1
                              assert   [1,2,3,4].max()     == 4
                              assert   [1,2,3,4].sum()     == 10
                              assert   [4,2,1,3].sort()    == [1,2,3,4]
                              assert   [4,2,1,3].findAll{ it%2 == 0 } == [4,2]
                                                                             Agile 2007 - 30
Maps…
                              def map   = [a:1, 'b':2]
                              println   map              //   [quot;aquot;:1, quot;bquot;:2]
                              println   map.a            //   1
                              println   map['a']         //   1
                              println   map.keySet()     //   [quot;aquot;, quot;bquot;]

                              map = [:]
                              // extend the map through assignment
Submission 631 © ASERT 2007




                              map[1] = 'a'; map[2] = 'b'
                              map[true] = 'p'; map[false] = 'q'
                              map[null] = 'x'; map['null'] = 'z'
                              assert map == [ 1:'a', 2:'b', (true):'p',
                                              (false):'q', (null):'x', 'null':'z' ]

                              def sb = new StringBuffer()
                              [1:'a', 2:'b', 3:'c'].each{ k, v-> sb << quot;$k:$v, quot; }
                              assert sb.toString() == '1:a, 2:b, 3:c, '

                              map = [1:'a', 2:'b', 3:'c']
                              def string = map.collect{ k, v -> quot;$k:$vquot; }.join(', ')
                              assert string == '1:a, 2:b, 3:c'
                                                                                       Agile 2007 - 31
…Maps
                              assert [
                                  [ name: 'Clark',    city: 'London' ],
                                  [ name: 'Sharma',   city: 'London' ],
                                  [ name: 'Maradona', city: 'LA'     ],
                                  [ name: 'Zhang',    city: 'HK'     ],
                                  [ name: 'Ali',      city: 'HK'     ],
                                  [ name: 'Liu',      city: 'HK'     ]
                              ].groupBy { it.city } == [
Submission 631 © ASERT 2007




                                  London: [
                                      [ name: 'Clark',    city: 'London'   ],
                                      [ name: 'Sharma',   city: 'London'   ]
                                  ], LA: [
                                      [ name: 'Maradona', city: 'LA'       ]
                                  ], HK: [
                                      [ name: 'Zhang',    city: 'HK'       ],
                                      [ name: 'Ali',      city: 'HK'       ],
                                      [ name: 'Liu',      city: 'HK'       ]
                                  ]
                              ]
                                                                                Agile 2007 - 32
Regular Expressions…
                              assert quot;Hello World!quot; =~ /Hello/       // Find operator
                              assert quot;Hello World!quot; ==~ /Hellob.*/ // Match operator
                              def p = ~/Hellob.*/                   // Pattern operator
                              assert p.class.name == 'java.util.regex.Pattern'

                              // replace matches with calculated values
Submission 631 © ASERT 2007




                              assert quot;1.23quot;.replaceAll(/./){ ch ->
                                  ch.next()
                              } == '2/34'

                              assert quot;1.23quot;.replaceAll(/d/){ num ->
                                  num.toInteger() + 1
                              } == '2.34'

                              assert quot;1.23quot;.replaceAll(/d+/){ num ->
                                  num.toInteger() + 1
                              } == '2.24'

                                                                                    Agile 2007 - 33
…Regular Expressions
                              str = 'groovy.codehaus.org and www.aboutgroovy.com'

                              re = '''(?x)           #   to enable whitespace and comments
                                    (                #   capture the hostname in $1
                                      (?:            #   these parens for grouping only
                                        (?! [-_] )   #   neither underscore nor dash lookahead
                                        [w-] +     #   hostname component
                                        .          #   and the domain dot
                                      )+             #   now repeat whole thing a few times
Submission 631 © ASERT 2007




                                      [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,
                                      quot;$adr [${InetAddress.getByName(adr).hostAddress}]quot;)
                              }
                              println out
                              // => groovy.codehaus.org [63.246.7.187]
                              // and www.aboutgroovy.com [63.246.7.76]
                                                                                                 Agile 2007 - 34
Control Structures

                              if (1) // ...                  switch (10) {
                              if (object) // ...               case 0             : /*   F */ ; break
                              if (list) // ...                 case 0..9          : //   F
                                                               case [8,9,11]      : //   F
                              for (item in iterable) { }       case Float         : //   F
Submission 631 © ASERT 2007




                                                               case {it % 3 == 0} : //   F
                              myMap.each { key, value ->       case ~/../         : //   T
                                  println quot;$key : $valuequot;      default            : //   F
                              }                              }

                              //   if (condition)...         // implement
                              //   else if (condition) ...   // boolean isCase(candidate)
                              //   else ...
                              //   throw, catch, finally
                              //   for, while
                              //   eachWithIndex, eachLine, ...



                                                                                               Agile 2007 - 35
GroovyBeans and GPath
                              class Dir {
                                  String name
                                  List   dirs
                              }

                              def root = new Dir (name: '/', dirs: [
                                  new Dir (name: 'a'),
Submission 631 © ASERT 2007




                                  new Dir (name: 'b')
                              ])

                              assert root.dirs[0].name == 'a'
                              assert root.dirs.name == ['a', 'b']
                              assert root.dirs.name*.size() == [1, 1]

                              def expected = ['getName', 'setName', 'getDirs', 'setDirs']
                              def accessorMethods = Dir.methods.name.grep(~/(g|s)et.*/)
                              assert accessorMethods.intersect(expected) == expected

                              // find, findAll, grep, every, any, …
                                                                                    Agile 2007 - 36
Static Imports
                                                                                Works with Java 1.4
                              import static java.awt.Color.LIGHT_GRAY
                                                                              Slightly more powerful
                              import static Boolean.FALSE as F
                                                                               than Java equivalent
                              import static Calendar.getInstance as now

                              println LIGHT_GRAY   // => java.awt.Color[r=192,g=192,b=192]
                              println !F           // => true
                              println now().time   // => Sun Apr 29 11:12:43 EST 2007
Submission 631 © ASERT 2007




                              import static Integer.*
                              println quot;Integers are between $MIN_VALUE and $MAX_VALUEquot;
                              // => Integers are between -2147483648 and 2147483647

                              def toHexString(int val, boolean upperCase) {
                                  def hexval = upperCase ?
                                      toHexString(val).toUpperCase() : toHexString(val)
                                  return '0x' + hexval
                              }
                              println toHexString(15, true)   // => 0xF
                              println toHexString(15, false) // => 0xf

                              import static Math.*
                              assert cos(2 * PI) == 1.0                                      Agile 2007 - 37
Topics
                              • Introduction
                              • Language Basics
                              Closures
                              • Builders
Submission 631 © ASERT 2007




                              • Data Access
                              • Other Features
                              • Testing with Groovy
                              • Further Integration
                              • Grails
                              • More Information
                                                          Agile 2007 - 38
Using Closures...
                              • Traditional mainstream languages
                                – Data can be stored in variables, passed around,
                                  combined in structured ways to form more complex
                                  data; code stays put where it is defined
                              • Languages supporting closures
Submission 631 © ASERT 2007




                                – Data and code can be stored in variables, passed
                                  around, combined in structured ways to form more
                                  complex algorithms and data
                                  doubleNum = { num -> num * 2 }
                                  println doubleNum(3) // => 6

                                  processThenPrint = { num, closure ->
                                      num = closure(num); println quot;num is $numquot;
                                  }
                                  processThenPrint(3, doubleNum)    // => num is 6
                                  processThenPrint(10) { it / 2 }   // => num is 5
                                                                                     Agile 2007 - 39
...Using Closures...
                              import static Math.*                Algorithm   piE   differs   by   1.0206946399193839E-11
                                                                  Algorithm   piF   differs   by   1.0070735356748628E-9
                                                                  Algorithm   piC   differs   by   2.668102068170697E-7
                              piA   =   {   22 / 7 }              Algorithm   piD   differs   by   4.813291008076703E-5
                              piB   =   {   333/106 }             Algorithm   piB   differs   by   8.321958979307098E-5
                                                                  Algorithm   piA   differs   by   0.001264489310206951
                              piC   =   {   355/113 }
                              piD   =   {   0.6 * (3 + sqrt(5)) }
                              piE   =   {   22/17 + 37/47 + 88/83 }
                              piF   =   {   sqrt(sqrt(2143/22)) }
Submission 631 © ASERT 2007




                              howCloseToPI = { abs(it.value() - PI) }

                              algorithms = [piA:piA, piB:piB, piC:piC,
                                            piD:piD, piE:piE, piF:piF]

                              findBestPI(algorithms)

                              def findBestPI(map) {
                                  map.entrySet().sort(howCloseToPI).each { entry ->
                                      def diff = howCloseToPI(entry)
                                      println quot;Algorithm $entry.key differs by $diffquot;
                                  }
                              }
                                                                                                               Agile 2007 - 40
...Using Closures...
                              • Used for many things in Groovy:
                                 •   Iterators                  new File('/x.txt').eachLine     {
                                                                    println it
                                 •   Callbacks                  }
                                 •   Higher-order functions
                                 •   Specialized control structures
Submission 631 © ASERT 2007




                                 •   Dynamic method definition
                                 •   Resource allocation       3.times { println 'Hi' }
                                 •   Threads
                                                               [0, 1, 2].each { number ->
                                 •   Continuations                 println number
                                                                 }
                              def houston(Closure doit) {
                                  (10..1).each { count ->        [0, 1, 2].each { println it}
                                      doit(count)
                                                                 def printit = { println it }
                                  }
                                                                 [0, 1, 2].each printit
                              }
                              houston { println it }
                                                                                          Agile 2007 - 41
...Using Closures...

                              map = ['a': 1, 'b': 2]
                              map.each {key, value -> map[key] = value * 2}
                              assert map == ['a': 2, 'b': 4]

                              doubler = {key, value -> map[key] = value * 2}
Submission 631 © ASERT 2007




                              map.each(doubler)
                              assert map == ['a': 4, 'b': 8]

                              def doubleMethod(entry) {
                                  map[entry.key] = entry.value * 2
                              }
                              doubler = this.&doubleMethod
                              map.each(doubler)
                              assert map == ['a': 8, 'b': 16]

                                                                          Agile 2007 - 42
...Using Closures...
                              assert [1, 2, 3].grep{ it < 3 } == [1, 2]
                              assert [1, 2, 3].any{ it % 2 == 0 }
                              assert [1, 2, 3].every{ it < 4 }
                              assert (1..9).collect{it}.join() == '123456789'
                              assert (1..4).collect{it * 2}.join() == '2468'
Submission 631 © ASERT 2007




                              def add = { x, y -> x + y }
                              def mult = { x, y -> x * y }
                              assert add(1, 3) == 4
                              assert mult(1, 3) == 3
                              def min = { x, y -> [x, y].min() }
                              def max = { x, y -> [x, y].max() }
                              def triple = mult.curry(3); assert triple(2) == 6
                              def atLeastTen = max.curry(10)
                              assert atLeastTen(5) == 10
                              assert atLeastTen(15) == 15
                                                                           Agile 2007 - 43
...Using Closures
                              def pairWise(list, Closure invoke) {
                                  if (list.size() < 2) return []
                                  def next = invoke(list[0], list[1])
                                  return [next] + pairWise(list[1..-1], invoke)
                              }
Submission 631 © ASERT 2007




                              // using min, max, etc. From previous   slide
                              assert pairWise(1..5, add) == [3, 5,    7, 9]
                              assert pairWise(1..5, mult) == [2, 6,   12, 20]
                              assert pairWise(1..5, min) == [1, 2,    3, 4]
                              assert pairWise(1..5, max) == [2, 3,    4, 5]

                              assert 'cbaxabc' == ['a', 'b', 'c'].inject('x') {
                                  result, item -> item + result + item
                              }
                                                                            Agile 2007 - 44
Topics
                              • Introduction
                              • Language Basics
                              • Closures
                              Builders
Submission 631 © ASERT 2007




                              • Data Access
                              • Other Features
                              • Testing with Groovy
                              • Further Integration
                              • Grails
                              • More Information
                                                          Agile 2007 - 45
Builder Pattern Inclusive
                               • Builder pattern from the GoF at the syntax-level
                               • Represents easily any nested tree-structured data


                              import groovy.xml.*               • Create new builder
                              def page = new MarkupBuilder()
Submission 631 © ASERT 2007




                                                                • Call pretended methods
                              page.html {
                                                                  (html, head, ...)
                                head { title 'Hello' }
                                body {
                                                                • Arguments are Closures
                                  ul {
                                                                • Builder code looks very
                                    for (count in 1..10) {
                                                                  declarative but is ordinary
                                      li quot;world $countquot;
                              }}}}                                Groovy program code and
                                                                  can contain any kind of
                                  NodeBuilder, DomBuilder,        logic
                                  SwingBuilder, AntBuilder, …

                                                                                        Agile 2007 - 46
SwingBuilder
                              import java.awt.FlowLayout
                              builder = new groovy.swing.SwingBuilder()
                              langs = [quot;Groovyquot;, quot;Rubyquot;, quot;Pythonquot;, quot;Pnutsquot;]

                              gui = builder.frame(size: [290, 100],
                                         title: 'Swinging with Groovy!’) {
                                  panel(layout: new FlowLayout()) {
                                      panel(layout: new FlowLayout()) {
Submission 631 © ASERT 2007




                                           for (lang in langs) {
                                               checkBox(text: lang)
                                           }
                                      }
                                      button(text: 'Groovy Button', actionPerformed: {
                                           builder.optionPane(message: 'Indubitably Groovy!').
                                               createDialog(null, 'Zen Message').show()
                                      })
                                      button(text: 'Groovy Quit',
                                               actionPerformed: {System.exit(0)})
                                  }
                              }
                              gui.show()
                               Source: http://www.ibm.com/developerworks/java/library/j-pg04125/
                                                                                                   Agile 2007 - 47
AntBuilder
                              def ant = new AntBuilder()

                              ant.echo(quot;helloquot;) // lets just call one task

                              // create a block of Ant using the builder pattern
                              ant.sequential {
                                  myDir = quot;target/AntTest/quot;
Submission 631 © ASERT 2007




                                  mkdir(dir: myDir)
                                  copy(todir: myDir) {
                                      fileset(dir: quot;src/testquot;) {
                                          include(name: quot;**/*.groovyquot;)
                                      }
                                  }
                                  echo(quot;donequot;)
                              }

                              // now lets do some normal Groovy again
                              file = new File(quot;target/test/AntTest.groovyquot;)
                              assert file.exists()
                                                                                   Agile 2007 - 48
Using AntLibs: Maven Ant Tasks & AntUnit…
                              def ant = new AntBuilder()

                              items = [[groupId:'jfree', artifactId:'jfreechart', version:'1.0.5'],
                                       [groupId:'jfree', artifactId:'jcommon', version:'1.0.9']]

                              def mvn = new AntLibHelper(ant:ant, namespace:'org.apache.maven.artifact.ant')
                              def antunit = new AntLibHelper(ant:ant, namespace:'org.apache.ant.antunit')
Submission 631 © ASERT 2007




                              // download artifacts with Maven Ant tasks
                              mvn.dependencies(filesetId:'artifacts') { items.each{ dependency(it) } }
                              // print out what we downloaded
                              ant.fileScanner { fileset(refid:'artifacts') }.each { println it }

                              // use AntUnit to confirm expected files were downloaded
                              def prefix = System.properties.'user.home' + '/.m2/repository'
                              items.each { item ->
                                 def g = item.groupId
                                 def a = item.artifactId
                                 def v = item.version
                                 antunit.assertFileExists(file:quot;$prefix/$g/$a/$v/$a-${v}.jarquot;)
                              }
                                                                                                         Agile 2007 - 49
…Using AntLibs: Maven Ant Tasks & AntUnit
                              ...
                              class AntLibHelper {
                                  def namespace, ant
                                  Object invokeMethod(String name, Object params) {
                                      ant.quot;antlib:$namespace:$namequot;(*params)
                                  }
                              }
Submission 631 © ASERT 2007




                              /* =>
                              Downloading: jfree/jfreechart/1.0.5/jfreechart-1.0.5.pom
                              Transferring 1K
                              Downloading: jfree/jcommon/1.0.9/jcommon-1.0.9.pom
                              Transferring 1K
                              Downloading: jfree/jfreechart/1.0.5/jfreechart-1.0.5.jar
                              Transferring 1157K
                              Downloading: jfree/jcommon/1.0.9/jcommon-1.0.9.jar
                              Transferring 298K
                              C:UsersPaul.m2repositoryjfreejcommon1.0.9jcommon-1.0.9.jar
                              C:UsersPaul.m2repositoryjfreejfreechart1.0.5jfreechart-1.0.5.jar
                              */



                                                                                                  Agile 2007 - 50
Topics
                              •   Introduction
                              •   Language Basics
                              •   Closures
                              •   Builders
                              Data Access
Submission 631 © ASERT 2007




                                   Objects
                                   XML
                                   Databases
                              •   Other Features
                              •   Testing with Groovy
                              •   Further Integration
                              •   Grails
                              •   More Information               Agile 2007 - 51
Uniform Data Access
                              • Data Access to Objects, XML, SQL
                                Databases has some differences and
                                some similarities
                                – Differences in detail about how to set up structures
                                – Similarities in how to process data within resulting
Submission 631 © ASERT 2007




                                  structures




                                                                                  Agile 2007 - 52
Object Data Access…
                              import java.text.SimpleDateFormat

                              class Athlete {
                                  def firstname, lastname, gender, country, dateOfBirth
                              }

                              def asDate(dateStr) {
                                  new SimpleDateFormat(quot;yyyy-MM-ddquot;).parse(dateStr)
Submission 631 © ASERT 2007




                              }

                              def athletes = [
                                  new Athlete(firstname: 'Paul', lastname: 'Tergat',
                                               dateOfBirth: '1969-06-17', gender: 'M', country:   'KEN'),
                                  new Athlete(firstname: 'Khalid', lastname: 'Khannouchi',
                                               dateOfBirth: '1971-12-22', gender: 'M', country:   'USA'),
                                  new Athlete(firstname: 'Sammy', lastname: 'Korir',
                                               dateOfBirth: '1971-12-12', gender: 'M', country:   'KEN'),
                                  new Athlete(firstname: 'Ronaldo', lastname: 'da Costa',
                                               dateOfBirth: '1970-06-07', gender: 'M', country:   'BRA'),
                                  new Athlete(firstname: 'Paula', lastname: 'Radcliffe',
                                               dateOfBirth: '1973-12-17', gender: 'F', country:   'GBR')
                              ]

                                                                                                    Agile 2007 - 53
…Object Data Access
                              def bornSince70 = {
                                  asDate(it.dateOfBirth) > asDate('1970-1-1') }
                              def excludingKh = { it.lastname <= 'Kg' ||
                                                  it.lastname >= 'Ki' }
                              def byGenderDescThenByCountry = { a, b ->
                                  a.gender == b.gender ?
Submission 631 © ASERT 2007




                                      a.country <=> b.country : b.gender <=> a.gender }

                              def someYoungsters = athletes.
                                  findAll(bornSince70).
                                  findAll(excludingKh).
                                  sort(byGenderDescThenByCountry)

                              someYoungsters.each {
                                  def name = quot;$it.firstname $it.lastnamequot;.padRight(25)
                                  println quot;$name ($it.gender) $it.country $it.dateOfBirthquot;
                              }

                                                                                     Agile 2007 - 54
Xml Data Access…
                              import java.text.SimpleDateFormat
                              import com.thoughtworks.xstream.XStream

                              class Athlete {
                                  String firstname, lastname, gender, country, dateOfBirth
                              }

                              def asDate(dateStr) { new SimpleDateFormat(quot;yyyy-MM-ddquot;).parse(dateStr) }
Submission 631 © ASERT 2007




                              def athleteList = [
                                  new Athlete(firstname: 'Paul', lastname: 'Tergat‘,
                                              dateOfBirth: '1969-06-17', gender: 'M', country:   'KEN'),
                                  new Athlete(firstname: 'Khalid', lastname: 'Khannouchi',
                                              dateOfBirth: '1971-12-22', gender: 'M', country:   'USA'),
                                  new Athlete(firstname: 'Sammy', lastname: 'Korir',
                                              dateOfBirth: '1971-12-12', gender: 'M', country:   'KEN'),
                                  new Athlete(firstname: 'Ronaldo', lastname: 'da Costa',
                                              dateOfBirth: '1970-06-07', gender: 'M', country:   'BRA'),
                                  new Athlete(firstname: 'Paula', lastname: 'Radcliffe',
                                              dateOfBirth: '1973-12-17', gender: 'F', country:   'GBR')
                              ]

                              // create XML as input
                              def input = new XStream().toXML(athleteList)
                                                                                                    Agile 2007 - 55
…Xml Data Access
                              def athletes = new XmlSlurper().parseText(input).Athlete

                              def bornSince70 = {
                                  asDate(it.dateOfBirth.text()) > asDate('1970-1-1') }
                              def excludingKh = { it.lastname.text() <= 'Kg' ||
                                                  it.lastname.text() >= 'Ki' }
                              def byGenderDescThenByCountry = { a, b ->
Submission 631 © ASERT 2007




                                  a.gender.text() == b.gender.text() ?
                                      a.country.text() <=> b.country.text() :
                                      b.gender.text() <=> a.gender.text() }

                              def someYoungsters = athletes.
                                  findAll(bornSince70).findAll(excludingKh).list().
                                  sort(byGenderDescThenByCountry)

                              someYoungsters.each {
                                  def name = quot;$it.firstname $it.lastnamequot;.padRight(25)
                                  println quot;$name ($it.gender) $it.country $it.dateOfBirthquot;
                              }
                                                                                      Agile 2007 - 56
Sql Data Access…
                              import groovy.sql.Sql

                              dbHandle = null

                              def getDb() {
                                  if (dbHandle) return dbHandle
                                  def source = new org.hsqldb.jdbc.jdbcDataSource()
                                  source.database = 'jdbc:hsqldb:mem:GIA'
                                  source.user = 'sa'
                                  source.password = ''
Submission 631 © ASERT 2007




                                  dbHandle = new Sql(source)
                                  return dbHandle
                              }

                              db.execute '''
                                  DROP    INDEX athleteIdx IF EXISTS;
                                  DROP    TABLE Athlete IF EXISTS;
                                  CREATE TABLE Athlete (
                                       athleteId   INTEGER GENERATED BY DEFAULT AS IDENTITY,
                                       firstname   VARCHAR(64),
                                       lastname    VARCHAR(64),
                                       country     VARCHAR(3),
                                       gender      CHAR(1),
                                       dateOfBirth DATE
                                  );
                                  CREATE INDEX athleteIdx ON Athlete (athleteId);
                              '''

                                                                                               Agile 2007 - 57
…Sql Data Access…
                              def athleteList = [
                                  [firstname: 'Paul', lastname: 'Tergat',
                                   dateOfBirth: '1969-06-17', gender: 'M', country:   'KEN'],
                                  [firstname: 'Khalid', lastname: 'Khannouchi',
                                   dateOfBirth: '1971-12-22', gender: 'M', country:   'USA'],
                                  [firstname: 'Sammy', lastname: 'Korir',
Submission 631 © ASERT 2007




                                   dateOfBirth: '1971-12-12', gender: 'M', country:   'KEN'],
                                  [firstname: 'Ronaldo', lastname: 'da Costa',
                                   dateOfBirth: '1970-06-07', gender: 'M', country:   'BRA'],
                                  [firstname: 'Paula', lastname: 'Radcliffe',
                                   dateOfBirth: '1973-12-17', gender: 'F', country:   'GBR']
                              ]

                              def athletes = db.dataSet('Athlete')
                              athleteList.each {a -> athletes.add(a)}



                                                                                       Agile 2007 - 58
…Sql Data Access
                              def bornSince70 = { it.dateOfBirth > '1970-1-1' }
                              def excludingKh = { it.lastname <= 'Kg' || it.lastname >= 'Ki' }

                              def someYoungsters = athletes.
                                  findAll(bornSince70).
                                  findAll(excludingKh).
                                  sort { it.gender }.reverse().      // * experimental
                                  sort { it.country }                // * experimental
Submission 631 © ASERT 2007




                              println someYoungsters.sql + 'n' + someYoungsters.parameters

                              someYoungsters.each {
                                  def name = quot;$it.firstname $it.lastnamequot;.padRight(25)
                                  println quot;$name ($it.gender)   $it.country   $it.dateOfBirthquot;
                              }
                              /* =>
                              select * from Athlete where dateOfBirth > ? and (lastname <= ? or lastname
                              >= ?) order by gender DESC, country
                              [quot;1970-1-1quot;, quot;Kgquot;, quot;Kiquot;]
                              Ronaldo da Costa          (M)   BRA   1970-06-07
                              Sammy Korir               (M)   KEN   1971-12-12
                              Paula Radcliffe           (F)   GBR   1973-12-17        */
                                                                                                  Agile 2007 - 59
More Details: XmlSlurper…
                              • Features
                                   – One-line parsing
                                   – GPath Syntax
                                   – Efficient lazy evaluation
                              static def CAR_RECORDS = '''
Submission 631 © ASERT 2007




                                 <records>
                                     <car name='HSV Maloo' make='Holden' year='2006'>
                                      <country>Australia</country>
                                      <record type='speed'>Production Pickup Truck with speed of 271kph</record>
                                     </car>
                                     <car name='P50' make='Peel' year='1962'>
                                      <country>Isle of Man</country>
                                      <record type='size'>Smallest Street-Legal Car at 99cm wide and 59 kg in weight</record>
                                     </car>
                                     <car name='Royale' make='Bugatti' year='1931'>
                                      <country>France</country>
                                      <record type='price'>Most Valuable Car at $15 million</record>
                                     </car>
                                 </records>
                                 '''
                                                                                                                  Agile 2007 - 60
…More Details: XmlSlurper
                              def records = new XmlSlurper().parseText(XmlExamples.CAR_RECORDS)
                              // 3 records in total
                              assert 3 == records.car.size()
                              // 10 nested nodes
                              assert 10 == records.depthFirst().collect{ it }.size()
                              // test properties of the first record
                              def firstRecord = records.car[0]
                              assert 'car' == firstRecord.name()
                              assert 'Holden' == firstRecord.@make.toString()
                              assert 'Australia' == firstRecord.country.text()
Submission 631 © ASERT 2007




                              // 2 cars have an 'e' in the make
                              assert 2 == records.car.findAll{ it.@make.toString().contains('e') }.size()
                              // 2 cars have an 'e' in the make
                              assert 2 == records.car.findAll{ it.@make =~ '.*e.*' }.size()
                              // makes of cars that have an 's' followed by an 'a' in the country
                              assert ['Holden', 'Peel'] == records.car.findAll{ it.country =~ '.*s.*a.*' }.@make.collect{ it.toString
                              // types of records
                              assert ['speed', 'size', 'price'] == records.depthFirst().grep{ it.@type != '' }.'@type'*.toString()
                              assert ['speed', 'size', 'price'] == records.'**'.grep{ it.@type != '' }.'@type'*.toString()
                              // check parent() operator
                              def countryOne = records.car[1].country
                              assert 'Peel' == countryOne.parent().@make.toString()
                              assert 'Peel' == countryOne.'..'.@make.toString()
                              // names of cars with records sorted by year
                              def names = records.car.list().sort{ it.@year.toInteger() }.'@name'*.toString()
                              assert ['Royale', 'P50', 'HSV Maloo'] == names
                                                                                                                        Agile 2007 - 61
More Details: Working with Databases
                              • Using standard SQL statements
                                  import groovy.sql.Sql

                                  def foo = 'cheese'
                                  def sql = Sql.newInstance(quot;jdbc:mysql://localhost:3306/mydbquot;, quot;userquot;,
                                                 quot;pswdquot;, quot;com.mysql.jdbc.Driverquot;)

                                  sql.eachRow(quot;select * from FOOD where type=${foo}quot;) {
Submission 631 © ASERT 2007




                                     println quot;Gromit likes ${it.name}quot;
                                  }

                              • Using DataSets
                                  import groovy.sql.Sql

                                  def sql = Sql.newInstance(quot;jdbc:mysql://localhost:3306/mydbquot;, quot;userquot;,
                                                 quot;pswdquot;, quot;com.mysql.jdbc.Driverquot;)

                                  def food = sql.dataSet('FOOD')
                                  def cheese = food.findAll { it.type == 'cheese' }
                                  cheese.each { println quot;Eat ${it.name}quot; }


                                                                                                          Agile 2007 - 62
DataSets and Lazy Evaluation
                              athleteSet = db.dataSet('Athlete')
                              youngsters = athleteSet.findAll{ it.dateOfBirth > '1970-1-1'}
                              paula = youngsters.findAll{ it.firstname == 'Paula'}

                              println paula.sql
                              // =>
Submission 631 © ASERT 2007




                              // select * from Athlete where dateOfBirth > ? and firstname = ?

                              println paula.parameters
                              // =>
                              // [1970-1-1, Paula]

                              paula.each { println it.lastname }     // database called here
                              // =>
                              // Radcliffe

                                                                                        Agile 2007 - 63
Topics
                              • Introduction
                              • Language Basics
                              • Closures
                              • Builders
Submission 631 © ASERT 2007




                              • Data Access
                              Other Features
                              • Testing with Groovy
                              • Further Integration
                              • Grails
                              • More Information
                                                          Agile 2007 - 64
JMX
                              import javax.management.remote.*
                              import javax.management.*
                              import javax.naming.Context

                              def urlRuntime = '/jndi/weblogic.management.mbeanservers.runtime'
                              def urlBase = 'service:jmx:t3://localhost:7001'

                              def serviceURL = new JMXServiceURL(urlBase + urlRuntime)
                              def h = new Hashtable()
                              h.put(Context.SECURITY_PRINCIPAL, 'weblogic')
Submission 631 © ASERT 2007




                              h.put(Context.SECURITY_CREDENTIALS, 'weblogic')
                              h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
                                      'weblogic.management.remote')
                              def server = JMXConnectorFactory.connect(serviceURL, h).mBeanServerConnection
                              def domainName = new ObjectName('com.bea:Name=RuntimeService,' +
                                      'Type=weblogic.management.mbeanservers.runtime.RuntimeServiceMBean')
                              def rtName = server.getAttribute(domainName, 'ServerRuntime')
                              def rt = new GroovyMBean(server, rtName)
                              println quot;Server: name=$rt.Name, state=$rt.State, version=$rt.WeblogicVersionquot;
                              def destFilter = Query.match(Query.attr('Type'), Query.value(
                                      'JMSDestinationRuntime'))
                              server.queryNames(new ObjectName('com.bea:*'), destFilter).each {name ->
                                  def jms = new GroovyMBean(server, name)
                                  println quot;JMS Destination: name=$jms.Name, type=$jms.DestinationTypequot; +
                                          quot;, messages=$jms.MessagesReceivedCountquot;
                              }

                                                                                                     Agile 2007 - 65
ExpandoMetaClass…
                              String.metaClass.swapCase = {->
                                  def sb = new StringBuffer()
                                  delegate.each {
                                      sb << (Character.isUpperCase(it as char) ?
                                          Character.toLowerCase(it as char) :
                                          Character.toUpperCase(it as char))
                                  }
Submission 631 © ASERT 2007




                                  sb.toString()
                              }

                              List.metaClass.sizeDoubled = {-> delegate.size() * 2 }

                              LinkedList list = []

                              list << 1
                              list << 2

                              assert 4 == list.sizeDoubled()
                                                                                   Agile 2007 - 66
…ExpandoMetaClass
                              class Person {
                                  String name
                              }

                              class MortgageLender {
                                 def borrowMoney() {
                                    quot;buy housequot;
Submission 631 © ASERT 2007




                                 }
                              }

                              def lender = new MortgageLender()

                              Person.metaClass.buyHouse = lender.&borrowMoney

                              def p = new Person()

                              assert quot;buy housequot; == p.buyHouse()


                                                                                Agile 2007 - 67
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy
groovy

Contenu connexe

Tendances

2012 04-09-v2-tdp-1167-cdi-bestpractices-final
2012 04-09-v2-tdp-1167-cdi-bestpractices-final2012 04-09-v2-tdp-1167-cdi-bestpractices-final
2012 04-09-v2-tdp-1167-cdi-bestpractices-finalRohit Kelapure
 
New Features of Java7 SE
New Features of Java7 SENew Features of Java7 SE
New Features of Java7 SEdogangoko
 
Consolidated shared indexes in real time
Consolidated shared indexes in real timeConsolidated shared indexes in real time
Consolidated shared indexes in real timeJeff Mace
 
10 generics a-4_in_1
10 generics a-4_in_110 generics a-4_in_1
10 generics a-4_in_1arasforever
 
Building Content Applications with JCR and OSGi
Building Content Applications with JCR and OSGiBuilding Content Applications with JCR and OSGi
Building Content Applications with JCR and OSGiCédric Hüsler
 
HowTo Build an OSGI EJB3 Server
HowTo Build an OSGI EJB3 ServerHowTo Build an OSGI EJB3 Server
HowTo Build an OSGI EJB3 Serverekkehard gentz
 
Java, Up to Date
Java, Up to DateJava, Up to Date
Java, Up to Date輝 子安
 
Garbage Collection for Dummies
Garbage Collection for DummiesGarbage Collection for Dummies
Garbage Collection for Dummies輝 子安
 

Tendances (8)

2012 04-09-v2-tdp-1167-cdi-bestpractices-final
2012 04-09-v2-tdp-1167-cdi-bestpractices-final2012 04-09-v2-tdp-1167-cdi-bestpractices-final
2012 04-09-v2-tdp-1167-cdi-bestpractices-final
 
New Features of Java7 SE
New Features of Java7 SENew Features of Java7 SE
New Features of Java7 SE
 
Consolidated shared indexes in real time
Consolidated shared indexes in real timeConsolidated shared indexes in real time
Consolidated shared indexes in real time
 
10 generics a-4_in_1
10 generics a-4_in_110 generics a-4_in_1
10 generics a-4_in_1
 
Building Content Applications with JCR and OSGi
Building Content Applications with JCR and OSGiBuilding Content Applications with JCR and OSGi
Building Content Applications with JCR and OSGi
 
HowTo Build an OSGI EJB3 Server
HowTo Build an OSGI EJB3 ServerHowTo Build an OSGI EJB3 Server
HowTo Build an OSGI EJB3 Server
 
Java, Up to Date
Java, Up to DateJava, Up to Date
Java, Up to Date
 
Garbage Collection for Dummies
Garbage Collection for DummiesGarbage Collection for Dummies
Garbage Collection for Dummies
 

Similaire à groovy

Groovy Testing Sep2009
Groovy Testing Sep2009Groovy Testing Sep2009
Groovy Testing Sep2009Paul King
 
Groovy Testing Aug2009
Groovy Testing Aug2009Groovy Testing Aug2009
Groovy Testing Aug2009guest4a266c
 
Groovy and Grails in Google App Engine
Groovy and Grails in Google App EngineGroovy and Grails in Google App Engine
Groovy and Grails in Google App EngineGuillaume Laforge
 
Terracotta Java Scalability - Stateless Versus Stateful Apps
Terracotta Java Scalability - Stateless Versus Stateful AppsTerracotta Java Scalability - Stateless Versus Stateful Apps
Terracotta Java Scalability - Stateless Versus Stateful AppsMatthew McCullough
 
Groovy Tutorial
Groovy TutorialGroovy Tutorial
Groovy TutorialPaul King
 
Project Zero For Javapolis 2007
Project Zero For Javapolis 2007Project Zero For Javapolis 2007
Project Zero For Javapolis 2007Jason McGee
 
Groovy Online 100
Groovy Online 100Groovy Online 100
Groovy Online 100reynolds
 
Asterisk-Java Framework Presentation
Asterisk-Java Framework PresentationAsterisk-Java Framework Presentation
Asterisk-Java Framework PresentationJustin Grammens
 
Peer Code Review: In a Nutshell and The Tantric Team: Getting Your Automated ...
Peer Code Review: In a Nutshell and The Tantric Team: Getting Your Automated ...Peer Code Review: In a Nutshell and The Tantric Team: Getting Your Automated ...
Peer Code Review: In a Nutshell and The Tantric Team: Getting Your Automated ...Atlassian
 
The Tantric Team: Getting Your Automated Build Groove On
The Tantric Team: Getting Your Automated Build Groove OnThe Tantric Team: Getting Your Automated Build Groove On
The Tantric Team: Getting Your Automated Build Groove OnAtlassian
 
Merb The Super Bike Of Frameworks
Merb The Super Bike Of FrameworksMerb The Super Bike Of Frameworks
Merb The Super Bike Of FrameworksRowan Hick
 
MarvinSketch and MarvinView: Tips And Tricks: US UGM 2008
MarvinSketch and MarvinView: Tips And Tricks: US UGM 2008MarvinSketch and MarvinView: Tips And Tricks: US UGM 2008
MarvinSketch and MarvinView: Tips And Tricks: US UGM 2008ChemAxon
 
AJUBY Open Source Application Builder
AJUBY Open Source Application BuilderAJUBY Open Source Application Builder
AJUBY Open Source Application Builderajuby
 
Galera Multi Master Synchronous My S Q L Replication Clusters
Galera  Multi Master  Synchronous  My S Q L  Replication  ClustersGalera  Multi Master  Synchronous  My S Q L  Replication  Clusters
Galera Multi Master Synchronous My S Q L Replication ClustersPerconaPerformance
 
Paulking groovy
Paulking groovyPaulking groovy
Paulking groovyd0nn9n
 
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...Paul King
 
Language-Oriented Programming and Language Workbenches: Building Domain Langu...
Language-Oriented Programming and Language Workbenches: Building Domain Langu...Language-Oriented Programming and Language Workbenches: Building Domain Langu...
Language-Oriented Programming and Language Workbenches: Building Domain Langu...elliando dias
 

Similaire à groovy (20)

Groovy Testing Sep2009
Groovy Testing Sep2009Groovy Testing Sep2009
Groovy Testing Sep2009
 
Groovy Testing Aug2009
Groovy Testing Aug2009Groovy Testing Aug2009
Groovy Testing Aug2009
 
Groovy and Grails in Google App Engine
Groovy and Grails in Google App EngineGroovy and Grails in Google App Engine
Groovy and Grails in Google App Engine
 
Terracotta Java Scalability - Stateless Versus Stateful Apps
Terracotta Java Scalability - Stateless Versus Stateful AppsTerracotta Java Scalability - Stateless Versus Stateful Apps
Terracotta Java Scalability - Stateless Versus Stateful Apps
 
Groovy Tutorial
Groovy TutorialGroovy Tutorial
Groovy Tutorial
 
Project Zero For Javapolis 2007
Project Zero For Javapolis 2007Project Zero For Javapolis 2007
Project Zero For Javapolis 2007
 
Groovy Online 100
Groovy Online 100Groovy Online 100
Groovy Online 100
 
Asterisk-Java Framework Presentation
Asterisk-Java Framework PresentationAsterisk-Java Framework Presentation
Asterisk-Java Framework Presentation
 
GlassFish v3 at JavaZone 09
GlassFish v3 at JavaZone 09GlassFish v3 at JavaZone 09
GlassFish v3 at JavaZone 09
 
Peer Code Review: In a Nutshell and The Tantric Team: Getting Your Automated ...
Peer Code Review: In a Nutshell and The Tantric Team: Getting Your Automated ...Peer Code Review: In a Nutshell and The Tantric Team: Getting Your Automated ...
Peer Code Review: In a Nutshell and The Tantric Team: Getting Your Automated ...
 
The Tantric Team: Getting Your Automated Build Groove On
The Tantric Team: Getting Your Automated Build Groove OnThe Tantric Team: Getting Your Automated Build Groove On
The Tantric Team: Getting Your Automated Build Groove On
 
GlassFish v3 Prelude Aquarium Paris
GlassFish v3 Prelude Aquarium ParisGlassFish v3 Prelude Aquarium Paris
GlassFish v3 Prelude Aquarium Paris
 
Merb The Super Bike Of Frameworks
Merb The Super Bike Of FrameworksMerb The Super Bike Of Frameworks
Merb The Super Bike Of Frameworks
 
MarvinSketch and MarvinView: Tips And Tricks: US UGM 2008
MarvinSketch and MarvinView: Tips And Tricks: US UGM 2008MarvinSketch and MarvinView: Tips And Tricks: US UGM 2008
MarvinSketch and MarvinView: Tips And Tricks: US UGM 2008
 
AJUBY Open Source Application Builder
AJUBY Open Source Application BuilderAJUBY Open Source Application Builder
AJUBY Open Source Application Builder
 
Galera Multi Master Synchronous My S Q L Replication Clusters
Galera  Multi Master  Synchronous  My S Q L  Replication  ClustersGalera  Multi Master  Synchronous  My S Q L  Replication  Clusters
Galera Multi Master Synchronous My S Q L Replication Clusters
 
Paulking groovy
Paulking groovyPaulking groovy
Paulking groovy
 
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
 
Whats New In Groovy 1.6?
Whats New In Groovy 1.6?Whats New In Groovy 1.6?
Whats New In Groovy 1.6?
 
Language-Oriented Programming and Language Workbenches: Building Domain Langu...
Language-Oriented Programming and Language Workbenches: Building Domain Langu...Language-Oriented Programming and Language Workbenches: Building Domain Langu...
Language-Oriented Programming and Language Workbenches: Building Domain Langu...
 

Plus de Shilong Sang

C:\Documents And Settings\User\桌面\Installation Guide O Oo3
C:\Documents And Settings\User\桌面\Installation Guide O Oo3C:\Documents And Settings\User\桌面\Installation Guide O Oo3
C:\Documents And Settings\User\桌面\Installation Guide O Oo3Shilong Sang
 
7月~12月份影片概况 0703更新
7月~12月份影片概况 0703更新7月~12月份影片概况 0703更新
7月~12月份影片概况 0703更新Shilong Sang
 
groovy经典入门
groovy经典入门groovy经典入门
groovy经典入门Shilong Sang
 
针对 Java程序员的 U M L概述
针对 Java程序员的 U M L概述针对 Java程序员的 U M L概述
针对 Java程序员的 U M L概述Shilong Sang
 
《狭义与广义相对论浅说》
《狭义与广义相对论浅说》《狭义与广义相对论浅说》
《狭义与广义相对论浅说》Shilong Sang
 
自己动手写操作系统
自己动手写操作系统自己动手写操作系统
自己动手写操作系统Shilong Sang
 
《最后期限》
《最后期限》《最后期限》
《最后期限》Shilong Sang
 
Spring基础教程
Spring基础教程Spring基础教程
Spring基础教程Shilong Sang
 

Plus de Shilong Sang (16)

C:\Documents And Settings\User\桌面\Installation Guide O Oo3
C:\Documents And Settings\User\桌面\Installation Guide O Oo3C:\Documents And Settings\User\桌面\Installation Guide O Oo3
C:\Documents And Settings\User\桌面\Installation Guide O Oo3
 
7月~12月份影片概况 0703更新
7月~12月份影片概况 0703更新7月~12月份影片概况 0703更新
7月~12月份影片概况 0703更新
 
Sexix
SexixSexix
Sexix
 
groovy经典入门
groovy经典入门groovy经典入门
groovy经典入门
 
针对 Java程序员的 U M L概述
针对 Java程序员的 U M L概述针对 Java程序员的 U M L概述
针对 Java程序员的 U M L概述
 
《狭义与广义相对论浅说》
《狭义与广义相对论浅说》《狭义与广义相对论浅说》
《狭义与广义相对论浅说》
 
人月神话
人月神话人月神话
人月神话
 
自己动手写操作系统
自己动手写操作系统自己动手写操作系统
自己动手写操作系统
 
《最后期限》
《最后期限》《最后期限》
《最后期限》
 
webwork2guide
webwork2guidewebwork2guide
webwork2guide
 
Spring基础教程
Spring基础教程Spring基础教程
Spring基础教程
 
Hibernate教程
Hibernate教程Hibernate教程
Hibernate教程
 
spring_jiaocheng
spring_jiaochengspring_jiaocheng
spring_jiaocheng
 
oracle
oracleoracle
oracle
 
Spring课件
Spring课件Spring课件
Spring课件
 
Spring课件
Spring课件Spring课件
Spring课件
 

Dernier

Famous Olympic Siblings from the 21st Century
Famous Olympic Siblings from the 21st CenturyFamous Olympic Siblings from the 21st Century
Famous Olympic Siblings from the 21st Centuryrwgiffor
 
Pharma Works Profile of Karan Communications
Pharma Works Profile of Karan CommunicationsPharma Works Profile of Karan Communications
Pharma Works Profile of Karan Communicationskarancommunications
 
Regression analysis: Simple Linear Regression Multiple Linear Regression
Regression analysis:  Simple Linear Regression Multiple Linear RegressionRegression analysis:  Simple Linear Regression Multiple Linear Regression
Regression analysis: Simple Linear Regression Multiple Linear RegressionRavindra Nath Shukla
 
Monte Carlo simulation : Simulation using MCSM
Monte Carlo simulation : Simulation using MCSMMonte Carlo simulation : Simulation using MCSM
Monte Carlo simulation : Simulation using MCSMRavindra Nath Shukla
 
Yaroslav Rozhankivskyy: Три складові і три передумови максимальної продуктивн...
Yaroslav Rozhankivskyy: Три складові і три передумови максимальної продуктивн...Yaroslav Rozhankivskyy: Три складові і три передумови максимальної продуктивн...
Yaroslav Rozhankivskyy: Три складові і три передумови максимальної продуктивн...Lviv Startup Club
 
Insurers' journeys to build a mastery in the IoT usage
Insurers' journeys to build a mastery in the IoT usageInsurers' journeys to build a mastery in the IoT usage
Insurers' journeys to build a mastery in the IoT usageMatteo Carbone
 
Grateful 7 speech thanking everyone that has helped.pdf
Grateful 7 speech thanking everyone that has helped.pdfGrateful 7 speech thanking everyone that has helped.pdf
Grateful 7 speech thanking everyone that has helped.pdfPaul Menig
 
A DAY IN THE LIFE OF A SALESMAN / WOMAN
A DAY IN THE LIFE OF A  SALESMAN / WOMANA DAY IN THE LIFE OF A  SALESMAN / WOMAN
A DAY IN THE LIFE OF A SALESMAN / WOMANIlamathiKannappan
 
7.pdf This presentation captures many uses and the significance of the number...
7.pdf This presentation captures many uses and the significance of the number...7.pdf This presentation captures many uses and the significance of the number...
7.pdf This presentation captures many uses and the significance of the number...Paul Menig
 
Ensure the security of your HCL environment by applying the Zero Trust princi...
Ensure the security of your HCL environment by applying the Zero Trust princi...Ensure the security of your HCL environment by applying the Zero Trust princi...
Ensure the security of your HCL environment by applying the Zero Trust princi...Roland Driesen
 
Event mailer assignment progress report .pdf
Event mailer assignment progress report .pdfEvent mailer assignment progress report .pdf
Event mailer assignment progress report .pdftbatkhuu1
 
Call Girls in Delhi, Escort Service Available 24x7 in Delhi 959961-/-3876
Call Girls in Delhi, Escort Service Available 24x7 in Delhi 959961-/-3876Call Girls in Delhi, Escort Service Available 24x7 in Delhi 959961-/-3876
Call Girls in Delhi, Escort Service Available 24x7 in Delhi 959961-/-3876dlhescort
 
Value Proposition canvas- Customer needs and pains
Value Proposition canvas- Customer needs and painsValue Proposition canvas- Customer needs and pains
Value Proposition canvas- Customer needs and painsP&CO
 
Call Girls In Panjim North Goa 9971646499 Genuine Service
Call Girls In Panjim North Goa 9971646499 Genuine ServiceCall Girls In Panjim North Goa 9971646499 Genuine Service
Call Girls In Panjim North Goa 9971646499 Genuine Serviceritikaroy0888
 
Call Girls In Holiday Inn Express Gurugram➥99902@11544 ( Best price)100% Genu...
Call Girls In Holiday Inn Express Gurugram➥99902@11544 ( Best price)100% Genu...Call Girls In Holiday Inn Express Gurugram➥99902@11544 ( Best price)100% Genu...
Call Girls In Holiday Inn Express Gurugram➥99902@11544 ( Best price)100% Genu...lizamodels9
 
Boost the utilization of your HCL environment by reevaluating use cases and f...
Boost the utilization of your HCL environment by reevaluating use cases and f...Boost the utilization of your HCL environment by reevaluating use cases and f...
Boost the utilization of your HCL environment by reevaluating use cases and f...Roland Driesen
 
RSA Conference Exhibitor List 2024 - Exhibitors Data
RSA Conference Exhibitor List 2024 - Exhibitors DataRSA Conference Exhibitor List 2024 - Exhibitors Data
RSA Conference Exhibitor List 2024 - Exhibitors DataExhibitors Data
 
0183760ssssssssssssssssssssssssssss00101011 (27).pdf
0183760ssssssssssssssssssssssssssss00101011 (27).pdf0183760ssssssssssssssssssssssssssss00101011 (27).pdf
0183760ssssssssssssssssssssssssssss00101011 (27).pdfRenandantas16
 
Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...
Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...
Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...amitlee9823
 

Dernier (20)

Famous Olympic Siblings from the 21st Century
Famous Olympic Siblings from the 21st CenturyFamous Olympic Siblings from the 21st Century
Famous Olympic Siblings from the 21st Century
 
Pharma Works Profile of Karan Communications
Pharma Works Profile of Karan CommunicationsPharma Works Profile of Karan Communications
Pharma Works Profile of Karan Communications
 
Regression analysis: Simple Linear Regression Multiple Linear Regression
Regression analysis:  Simple Linear Regression Multiple Linear RegressionRegression analysis:  Simple Linear Regression Multiple Linear Regression
Regression analysis: Simple Linear Regression Multiple Linear Regression
 
Monte Carlo simulation : Simulation using MCSM
Monte Carlo simulation : Simulation using MCSMMonte Carlo simulation : Simulation using MCSM
Monte Carlo simulation : Simulation using MCSM
 
Yaroslav Rozhankivskyy: Три складові і три передумови максимальної продуктивн...
Yaroslav Rozhankivskyy: Три складові і три передумови максимальної продуктивн...Yaroslav Rozhankivskyy: Три складові і три передумови максимальної продуктивн...
Yaroslav Rozhankivskyy: Три складові і три передумови максимальної продуктивн...
 
Insurers' journeys to build a mastery in the IoT usage
Insurers' journeys to build a mastery in the IoT usageInsurers' journeys to build a mastery in the IoT usage
Insurers' journeys to build a mastery in the IoT usage
 
Grateful 7 speech thanking everyone that has helped.pdf
Grateful 7 speech thanking everyone that has helped.pdfGrateful 7 speech thanking everyone that has helped.pdf
Grateful 7 speech thanking everyone that has helped.pdf
 
A DAY IN THE LIFE OF A SALESMAN / WOMAN
A DAY IN THE LIFE OF A  SALESMAN / WOMANA DAY IN THE LIFE OF A  SALESMAN / WOMAN
A DAY IN THE LIFE OF A SALESMAN / WOMAN
 
7.pdf This presentation captures many uses and the significance of the number...
7.pdf This presentation captures many uses and the significance of the number...7.pdf This presentation captures many uses and the significance of the number...
7.pdf This presentation captures many uses and the significance of the number...
 
Ensure the security of your HCL environment by applying the Zero Trust princi...
Ensure the security of your HCL environment by applying the Zero Trust princi...Ensure the security of your HCL environment by applying the Zero Trust princi...
Ensure the security of your HCL environment by applying the Zero Trust princi...
 
Event mailer assignment progress report .pdf
Event mailer assignment progress report .pdfEvent mailer assignment progress report .pdf
Event mailer assignment progress report .pdf
 
Forklift Operations: Safety through Cartoons
Forklift Operations: Safety through CartoonsForklift Operations: Safety through Cartoons
Forklift Operations: Safety through Cartoons
 
Call Girls in Delhi, Escort Service Available 24x7 in Delhi 959961-/-3876
Call Girls in Delhi, Escort Service Available 24x7 in Delhi 959961-/-3876Call Girls in Delhi, Escort Service Available 24x7 in Delhi 959961-/-3876
Call Girls in Delhi, Escort Service Available 24x7 in Delhi 959961-/-3876
 
Value Proposition canvas- Customer needs and pains
Value Proposition canvas- Customer needs and painsValue Proposition canvas- Customer needs and pains
Value Proposition canvas- Customer needs and pains
 
Call Girls In Panjim North Goa 9971646499 Genuine Service
Call Girls In Panjim North Goa 9971646499 Genuine ServiceCall Girls In Panjim North Goa 9971646499 Genuine Service
Call Girls In Panjim North Goa 9971646499 Genuine Service
 
Call Girls In Holiday Inn Express Gurugram➥99902@11544 ( Best price)100% Genu...
Call Girls In Holiday Inn Express Gurugram➥99902@11544 ( Best price)100% Genu...Call Girls In Holiday Inn Express Gurugram➥99902@11544 ( Best price)100% Genu...
Call Girls In Holiday Inn Express Gurugram➥99902@11544 ( Best price)100% Genu...
 
Boost the utilization of your HCL environment by reevaluating use cases and f...
Boost the utilization of your HCL environment by reevaluating use cases and f...Boost the utilization of your HCL environment by reevaluating use cases and f...
Boost the utilization of your HCL environment by reevaluating use cases and f...
 
RSA Conference Exhibitor List 2024 - Exhibitors Data
RSA Conference Exhibitor List 2024 - Exhibitors DataRSA Conference Exhibitor List 2024 - Exhibitors Data
RSA Conference Exhibitor List 2024 - Exhibitors Data
 
0183760ssssssssssssssssssssssssssss00101011 (27).pdf
0183760ssssssssssssssssssssssssssss00101011 (27).pdf0183760ssssssssssssssssssssssssssss00101011 (27).pdf
0183760ssssssssssssssssssssssssssss00101011 (27).pdf
 
Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...
Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...
Call Girls Jp Nagar Just Call 👗 7737669865 👗 Top Class Call Girl Service Bang...
 

groovy

  • 1. Submission 631 © ASERT 2007 Groovy Tutorial Dr Paul King ASERT, Australia Agile 2007 - 1
  • 2. Topics Introduction • Language Basics • Closures • Builders • Submission 631 © ASERT 2007 Data Access • Other Features • Testing with Groovy • Further Integration • Grails • More Information Agile 2007 - 2
  • 3. What is Groovy? • “Groovy is like a super version of Java. It can leverage Java's enterprise capabilities but also has cool productivity features like closures, Submission 631 © ASERT 2007 DSL support, builders and dynamic typing.” Groovy = Java – boiler plate code + optional dynamic typing + closures + domain specific languages + builders + metaprogramming Agile 2007 - 3
  • 4. Groovy Goodies Overview • Fully object oriented • Closures: reusable and assignable pieces of code • Operators can be • GPath: efficient Submission 631 © ASERT 2007 overloaded object navigation • Multimethods • GroovyBeans • Literal declaration for • grep and switch lists (arrays), maps, • Templates, builder, ranges and regular swing, Ant, markup, expressions XML, SQL, XML-RPC, Scriptom, Grails, tests, Mocks Agile 2007 - 4
  • 5. Growing Acceptance • A slow and steady start but now gaining in momentum; growing in maturity & mindshare Submission 631 © ASERT 2007 Groovy Recipes Pragmatic Bookshelf Agile 2007 - 5
  • 6. The Landscape of JVM Languages optional static types Submission 631 © ASERT 2007 Dynamic features call for dynamic types Java bytecode calls for static types The terms “Java Virtual Machine” and “JVM” mean a Virtual Machine for the Java™ platform. Agile 2007 - 6
  • 7. Groovy Starter System.out.println(quot;Hello, World!quot;); // optional semicolon, println 'Hello, World!' // System.out, brackets, // main() method def name = 'Guillaume' // dynamic typing println quot;$name, I'll get the car.quot; // GString String longer = quot;quot;quot;${name}, the car Submission 631 © ASERT 2007 is in the next row.quot;quot;quot; // multi-line string // with static typing assert 0.5 == 1/2 // BigDecimal equals() def printSize(obj) { // optional duck typing print obj?.size() // safe dereferencing } def animals = ['ant', 'bee', 'cat'] // native list syntax assert animals.every { pet -> // closure support pet < 'dog' // overloading } Agile 2007 - 7
  • 8. A Better Java... import java.util.List; import java.util.ArrayList; class Erase { This code private List filterLongerThan(List strings, int length) { List result = new ArrayList(); is valid for (int i = 0; i < strings.size(); i++) { Java and String s = (String) strings.get(i); if (s.length() <= length) { valid Groovy result.add(s); Submission 631 © ASERT 2007 } } return result; } public static void main(String[] args) { List names = new ArrayList(); names.add(quot;Tedquot;); names.add(quot;Fredquot;); names.add(quot;Jedquot;); names.add(quot;Nedquot;); Based on an System.out.println(names); example by Erase e = new Erase(); List shortNames = e.filterLongerThan(names, 3); Jim Weirich System.out.println(shortNames.size()); & Ted Leung for (int i = 0; i < shortNames.size(); i++) { String s = (String) shortNames.get(i); System.out.println(s); } } } Agile 2007 - 8
  • 9. ...A Better Java... import java.util.List; import java.util.ArrayList; class Erase { Do the private List filterLongerThan(List strings, int length) { List result = new ArrayList(); semicolons for (int i = 0; i < strings.size(); i++) { add anything? String s = (String) strings.get(i); if (s.length() <= length) { And shouldn’t result.add(s); Submission 631 © ASERT 2007 } we us more } modern list return result; } notation? public static void main(String[] args) { List names = new ArrayList(); Why not names.add(quot;Tedquot;); names.add(quot;Fredquot;); names.add(quot;Jedquot;); names.add(quot;Nedquot;); import common System.out.println(names); libraries? Erase e = new Erase(); List shortNames = e.filterLongerThan(names, 3); System.out.println(shortNames.size()); for (int i = 0; i < shortNames.size(); i++) { String s = (String) shortNames.get(i); System.out.println(s); } } } Agile 2007 - 9
  • 10. ...A Better Java... class Erase { private List filterLongerThan(List strings, int length) { List result = new ArrayList() for (String s in strings) { if (s.length() <= length) { result.add(s) } } return result } Submission 631 © ASERT 2007 public static void main(String[] args) { List names = new ArrayList() names.add(quot;Tedquot;); names.add(quot;Fredquot;) names.add(quot;Jedquot;); names.add(quot;Nedquot;) System.out.println(names) Erase e = new Erase() List shortNames = e.filterLongerThan(names, 3) System.out.println(shortNames.size()) for (String s in shortNames) { System.out.println(s) } } } Agile 2007 - 10
  • 11. ...A Better Java... class Erase { private List filterLongerThan(List strings, int length) { List result = new ArrayList() for (String s in strings) { if (s.length() <= length) { Do we need result.add(s) the static types? } } Must we always return result } have a main Submission 631 © ASERT 2007 method and public static void main(String[] args) { List names = new ArrayList() class definition? names.add(quot;Tedquot;); names.add(quot;Fredquot;) names.add(quot;Jedquot;); names.add(quot;Nedquot;) How about System.out.println(names) Erase e = new Erase() improved List shortNames = e.filterLongerThan(names, 3) consistency? System.out.println(shortNames.size()) for (String s in shortNames) { System.out.println(s) } } } Agile 2007 - 11
  • 12. ...A Better Java... def filterLongerThan(strings, length) { def result = new ArrayList() for (s in strings) { if (s.size() <= length) { result.add(s) } } return result Submission 631 © ASERT 2007 } names = new ArrayList() names.add(quot;Tedquot;) names.add(quot;Fredquot;) names.add(quot;Jedquot;) names.add(quot;Nedquot;) System.out.println(names) shortNames = filterLongerThan(names, 3) System.out.println(shortNames.size()) for (s in shortNames) { System.out.println(s) } Agile 2007 - 12
  • 13. ...A Better Java... def filterLongerThan(strings, length) { def result = new ArrayList() for (s in strings) { if (s.size() <= length) { Shouldn’t we result.add(s) } have special } notation for lists? return result Submission 631 © ASERT 2007 } And special facilities for names = new ArrayList() names.add(quot;Tedquot;) list processing? names.add(quot;Fredquot;) names.add(quot;Jedquot;) names.add(quot;Nedquot;) System.out.println(names) shortNames = filterLongerThan(names, 3) System.out.println(shortNames.size()) for (s in shortNames) { System.out.println(s) } Agile 2007 - 13
  • 14. ...A Better Java... def filterLongerThan(strings, length) { return strings.findAll{ it.size() <= length } } names = [quot;Tedquot;, quot;Fredquot;, quot;Jedquot;, quot;Nedquot;] System.out.println(names) shortNames = filterLongerThan(names, 3) System.out.println(shortNames.size()) Submission 631 © ASERT 2007 shortNames.each{ System.out.println(s) } Agile 2007 - 14
  • 15. ...A Better Java... def filterLongerThan(strings, length) { return strings.findAll{ it.size() <= length } } Is the method now needed? names = [quot;Tedquot;, quot;Fredquot;, quot;Jedquot;, quot;Nedquot;] System.out.println(names) Easier ways to shortNames = filterLongerThan(names, 3) use common System.out.println(shortNames.size()) Submission 631 © ASERT 2007 shortNames.each{ System.out.println(s) } methods? Are brackets required here? Agile 2007 - 15
  • 16. ...A Better Java... names = [quot;Tedquot;, quot;Fredquot;, quot;Jedquot;, quot;Nedquot;] println names shortNames = names.findAll{ it.size() <= 3 } println shortNames.size() shortNames.each{ println it } Submission 631 © ASERT 2007 [quot;Tedquot;, quot;Fredquot;, quot;Jedquot;, quot;Nedquot;] 3 Ted Jed Ned Agile 2007 - 16
  • 17. ...A Better Java names = [quot;Tedquot;, quot;Fredquot;, quot;Jedquot;, quot;Nedquot;] println names shortNames = names.findAll{ it.size() <= 3 } println shortNames.size() shortNames.each{ println it } import java.util.List; Submission 631 © ASERT 2007 import java.util.ArrayList; class Erase { private List filterLongerThan(List strings, int length) { List result = new ArrayList(); for (int i = 0; i < strings.size(); i++) { String s = (String) strings.get(i); if (s.length() <= length) { result.add(s); } } return result; } public static void main(String[] args) { List names = new ArrayList(); names.add(quot;Tedquot;); names.add(quot;Fredquot;); names.add(quot;Jedquot;); names.add(quot;Nedquot;); System.out.println(names); Erase e = new Erase(); List shortNames = e.filterLongerThan(names, 3); System.out.println(shortNames.size()); for (int i = 0; i < shortNames.size(); i++) { String s = (String) shortNames.get(i); System.out.println(s); } } } Agile 2007 - 17
  • 18. Better JavaBeans... import java.math.BigDecimal; ... public class BikeJavaBean { public void setModel(String model) { private String manufacturer; this.model = model; private String model; } private int frame; private String serialNo; public int getFrame() { private double weight; return frame; private String status; } private BigDecimal cost; public String getSerialNo() { public BikeJavaBean(String manufacturer, String model, return serialNo; int frame, String serialNo, } double weight, String status) { this.manufacturer = manufacturer; public void setSerialNo(String serialNo) { this.model = model; this.serialNo = serialNo; Submission 631 © ASERT 2007 this.frame = frame; } this.serialNo = serialNo; this.weight = weight; public double getWeight() { this.status = status; return weight; } } public String toString() { public void setWeight(double weight) { return quot;Bike:‚ + this.weight = weight; ‚n manufacturer -- quot; + manufacturer + } quot;n model -- quot; + model + quot;n frame -- quot; + frame + public String getStatus() { quot;n serialNo -- quot; + serialNo + return status; quot;nquot;; } } public void setStatus(String status) { public String getManufacturer() { this.status = status; return manufacturer; } } public BigDecimal getCost() { public void setManufacturer(String manufacturer) { return cost; this.manufacturer = manufacturer; } } public void setCost(BigDecimal cost) { public String getModel() { this.cost = cost.setScale(3, BigDecimal.ROUND_HALF_UP); return model; } } } ... Modified example from: http://www.ibm.com/developerworks/library/j-pg09196.html Agile 2007 - 18
  • 19. ...Better JavaBeans... import java.math.BigDecimal; ... Auto public class BikeJavaBean { public void setModel(String model) { private String manufacturer; this.model = model; getters? private String model; } private int frame; Auto private String serialNo; public int getFrame() { private double weight; return frame; private String status; } setters? private BigDecimal cost; public String getSerialNo() { public BikeJavaBean(String manufacturer, String model, return serialNo; Auto int frame, String serialNo, } double weight, String status) { construction? this.manufacturer = manufacturer; public void setSerialNo(String serialNo) { this.model = model; this.serialNo = serialNo; Submission 631 © ASERT 2007 this.frame = frame; } this.serialNo = serialNo; this.weight = weight; public double getWeight() { this.status = status; return weight; } } public String toString() { public void setWeight(double weight) { return quot;Bike:‚ + this.weight = weight; ‚n manufacturer -- quot; + manufacturer + } quot;n model -- quot; + model + quot;n frame -- quot; + frame + public String getStatus() { quot;n serialNo -- quot; + serialNo + return status; quot;nquot;; } } public void setStatus(String status) { public String getManufacturer() { this.status = status; return manufacturer; } } public BigDecimal getCost() { public void setManufacturer(String manufacturer) { return cost; this.manufacturer = manufacturer; } } public void setCost(BigDecimal cost) { public String getModel() { this.cost = cost.setScale(3, BigDecimal.ROUND_HALF_UP); return model; } } } ... Agile 2007 - 19
  • 20. ... Better JavaBeans class BikeGroovyBean { String manufacturer, model, serialNo, status final Integer frame Double weight BigDecimal cost public void setCost(BigDecimal newCost) { Submission 631 © ASERT 2007 cost = newCost.setScale(3, BigDecimal.ROUND_HALF_UP) } public String toString() { return quot;quot;quot;Bike: manufacturer -- $manufacturer model -- $model frame -- $frame serialNo -- $serialNo quot;quot;quot; } } Agile 2007 - 20
  • 21. Topics • Introduction Language Basics • Closures • Builders Submission 631 © ASERT 2007 • Data Access • Other Features • Testing with Groovy • Further Integration • Grails • More Information Agile 2007 - 21
  • 22. Strings… • Several forms – Single quotes for // normal strings simple strings def firstname = 'Kate' def surname= quot;Bushquot; – Double quotes for assert firstname * 2 == 'KateKate' GStrings which // GString support variable Submission 631 © ASERT 2007 def fullname = quot;$firstname $surnamequot; expansion assert fullname == 'Kate Bush' – Slashy strings assert fullname - firstname == ' Bush' assert fullname.padLeft(10) == behave like ' Kate Bush' GStrings but // indexing (including ranges) preserve assert fullname[0..3] == firstname backslashes (great assert fullname[-4..-1] == surname for regex and assert fullname[5, 3..1] == 'Beta' directory names) – Multi-line versions Agile 2007 - 22
  • 23. …Strings… // slashy string: (almost) no escaping // Multi-line strings def path = /C:WindowsSystem32/ def twister = ''' She sells, sea shells def plain = 'nrtbf$' By the sea shore''' assert plain.size() == 7 def slashy = /nrtbf$/ def lines = assert slashy.size() == 14 twister.split('n') Submission 631 © ASERT 2007 assert lines.size() == 2 // late binding trick with closures fullname = quot;${-> firstname} $surnamequot; def address = quot;quot;quot; assert fullname == 'Kate Bush' $fullname firstname = 'George' 123 First Ave surname = 'Clooney' New York assert fullname == 'George Bush' quot;quot;quot;.trim() println quot;quot;quot; def lines = ---------------------- address.split('n') | $fullname | assert lines.size() == 3 | 123 First Ave | | New York | ---------------------- quot;quot;quot; Agile 2007 - 23
  • 24. …Strings // more substrings string = 'hippopotamus' assert string - 'hippo' - 'mus' + 'to' == 'potato' assert string.replace('ppopotam','bisc') == 'hibiscus' // processing characters assert 'apple'.toList() == ['a', 'p', 'p', 'l', 'e'] //also: 'apple' as String[], 'apple'.split(''), 'apple'.each{} Submission 631 © ASERT 2007 string = quot;an apple a dayquot; assert string.toList().unique().sort().join() == ' adelnpy' // reversing chars/words assert 'string'.reverse() == 'gnirts' string = 'Yoda said, quot;can you see this?quot;' revwords = string.split(' ').toList().reverse().join(' ') assert revwords == 'this?quot; see you quot;can said, Yoda' words = ['bob', 'alpha', 'rotator', 'omega', 'reviver'] bigPalindromes = words.findAll{w -> w == w.reverse() && w.size() > 5} assert bigPalindromes == ['rotator', 'reviver'] Agile 2007 - 24
  • 25. Numbers... • Java Approach – Supports primitive types and object types – Has wrapper classes to allow conversion – Java 5+ has autoboxing to hide difference • Groovy Approach Submission 631 © ASERT 2007 – Treats everything as an object at the language level • And does appropriate autoboxing under the covers when integrating with Java – BigDecimal used as the default type for non-Integers – Operator overloading applies to all common operations on numbers, e.g. 3 * 4 is the same as 3.multiply(4) • You can use these operators for your own types, e.g. Person * 3 calls the multiple method on your person object Agile 2007 - 25
  • 26. ...Numbers def x = 3 def y = 4 assert x + y == 7 assert x.plus(y) == 7 assert x instanceof Integer assert 0.5 == 1/2 // uses BigDecimal arithmetic as default def a = 2 / 3 // 0.6666666666 def b = a.setScale(3, BigDecimal.ROUND_HALF_UP) assert b.toString() == '0.667' Submission 631 © ASERT 2007 assert 4 + 3 == 7 // 4.plus(3) assert 4 - 3 == 1 // 4.minus(3) assert 4 * 3 == 12 // 4.multiply(12) assert 4 % 3 == 1 // 4.mod(3) assert 4 ** 3 == 64 // 4.power(3) assert 4 / 3 == 1.3333333333 // 4.div(3) assert 4.intdiv(3) == 1 // normal integer division assert !(4 == 3) // !(4.equals(3)) assert 4 != 3 // ! 4.equals(3) assert !(4 < 3) // 4.compareTo(3) <0 assert !(4 <= 3) // 4.compareTo(3) <= 0 assert 4>3 // 4.compareTo(3) >0 assert 4 >= 3 // 4.compareTo(3) >= 0 assert 4 <=> 3 == 1 // 4.compareTo(3) Agile 2007 - 26
  • 27. Dates... • Mostly same support as Java • Use java.util.Date or java.util.Calendar – Or java.sql.Date etc. – Can use static imports to help • Or 3rd party package like Joda Time Submission 631 © ASERT 2007 • Does have special support for changing times: date2 = date1 + 1.week – 3.days + 6.hours • More utility methods expected for inputting and outputting dates • Potentially will change with JSR 310 Agile 2007 - 27
  • 28. ...Dates import static java.util.Calendar.getInstance as now import org.codehaus.groovy.runtime.TimeCategory import java.text.SimpleDateFormat println now().time Thu Jun 28 10:10:34 EST 2007 Fri Jun 29 10:10:35 EST 2007 def date = new Date() + 1 Tue Jul 17 11:10:35 EST 2007 Submission 631 © ASERT 2007 println date Date was Jun/03/1998 use(TimeCategory) { println new Date() + 1.hour + 3.weeks - 2.days } input = quot;1998-06-03quot; df1 = new SimpleDateFormat(quot;yyyy-MM-ddquot;) date = df1.parse(input) df2 = new SimpleDateFormat(quot;MMM/dd/yyyyquot;) println 'Date was ' + df2.format(date) Agile 2007 - 28
  • 29. Lists, Maps, Ranges • Lists – Special syntax for list literals – Additional common methods (operator overloading) def list = [3, new Date(), 'Jan'] assert list + list == list * 2 Submission 631 © ASERT 2007 • Maps – Special syntax for map literals – Additional common methods def map = [a: 1, b: 2] assert map['a'] == 1 && map.b == 2 • Ranges – Special syntax for various kinds of ranges def letters = 'a'..'z' def numbers = 0..<10 Agile 2007 - 29
  • 30. Lists assert [1,2,3,4] == (1..4) assert [1,2,3] + [1] == [1,2,3,1] assert [1,2,3] << 1 == [1,2,3,1] assert [1,2,3,1] - [1] == [2,3] assert [1,2,3] * 2 == [1,2,3,1,2,3] assert [1,[2,3]].flatten() == [1,2,3] assert [1,2,3].reverse() == [3,2,1] Submission 631 © ASERT 2007 assert [1,2,3].disjoint([4,5,6]) assert [1,2,3].intersect([4,3,1]) == [3,1] assert [1,2,3].collect{ it+3 } == [4,5,6] assert [1,2,3,1].unique().size() == 3 assert [1,2,3,1].count(1) == 2 assert [1,2,3,4].min() == 1 assert [1,2,3,4].max() == 4 assert [1,2,3,4].sum() == 10 assert [4,2,1,3].sort() == [1,2,3,4] assert [4,2,1,3].findAll{ it%2 == 0 } == [4,2] Agile 2007 - 30
  • 31. Maps… def map = [a:1, 'b':2] println map // [quot;aquot;:1, quot;bquot;:2] println map.a // 1 println map['a'] // 1 println map.keySet() // [quot;aquot;, quot;bquot;] map = [:] // extend the map through assignment Submission 631 © ASERT 2007 map[1] = 'a'; map[2] = 'b' map[true] = 'p'; map[false] = 'q' map[null] = 'x'; map['null'] = 'z' assert map == [ 1:'a', 2:'b', (true):'p', (false):'q', (null):'x', 'null':'z' ] def sb = new StringBuffer() [1:'a', 2:'b', 3:'c'].each{ k, v-> sb << quot;$k:$v, quot; } assert sb.toString() == '1:a, 2:b, 3:c, ' map = [1:'a', 2:'b', 3:'c'] def string = map.collect{ k, v -> quot;$k:$vquot; }.join(', ') assert string == '1:a, 2:b, 3:c' Agile 2007 - 31
  • 32. …Maps assert [ [ name: 'Clark', city: 'London' ], [ name: 'Sharma', city: 'London' ], [ name: 'Maradona', city: 'LA' ], [ name: 'Zhang', city: 'HK' ], [ name: 'Ali', city: 'HK' ], [ name: 'Liu', city: 'HK' ] ].groupBy { it.city } == [ Submission 631 © ASERT 2007 London: [ [ name: 'Clark', city: 'London' ], [ name: 'Sharma', city: 'London' ] ], LA: [ [ name: 'Maradona', city: 'LA' ] ], HK: [ [ name: 'Zhang', city: 'HK' ], [ name: 'Ali', city: 'HK' ], [ name: 'Liu', city: 'HK' ] ] ] Agile 2007 - 32
  • 33. Regular Expressions… assert quot;Hello World!quot; =~ /Hello/ // Find operator assert quot;Hello World!quot; ==~ /Hellob.*/ // Match operator def p = ~/Hellob.*/ // Pattern operator assert p.class.name == 'java.util.regex.Pattern' // replace matches with calculated values Submission 631 © ASERT 2007 assert quot;1.23quot;.replaceAll(/./){ ch -> ch.next() } == '2/34' assert quot;1.23quot;.replaceAll(/d/){ num -> num.toInteger() + 1 } == '2.34' assert quot;1.23quot;.replaceAll(/d+/){ num -> num.toInteger() + 1 } == '2.24' Agile 2007 - 33
  • 34. …Regular Expressions str = 'groovy.codehaus.org and www.aboutgroovy.com' re = '''(?x) # to enable whitespace and comments ( # capture the hostname in $1 (?: # these parens for grouping only (?! [-_] ) # neither underscore nor dash lookahead [w-] + # hostname component . # and the domain dot )+ # now repeat whole thing a few times Submission 631 © ASERT 2007 [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, quot;$adr [${InetAddress.getByName(adr).hostAddress}]quot;) } println out // => groovy.codehaus.org [63.246.7.187] // and www.aboutgroovy.com [63.246.7.76] Agile 2007 - 34
  • 35. Control Structures if (1) // ... switch (10) { if (object) // ... case 0 : /* F */ ; break if (list) // ... case 0..9 : // F case [8,9,11] : // F for (item in iterable) { } case Float : // F Submission 631 © ASERT 2007 case {it % 3 == 0} : // F myMap.each { key, value -> case ~/../ : // T println quot;$key : $valuequot; default : // F } } // if (condition)... // implement // else if (condition) ... // boolean isCase(candidate) // else ... // throw, catch, finally // for, while // eachWithIndex, eachLine, ... Agile 2007 - 35
  • 36. GroovyBeans and GPath class Dir { String name List dirs } def root = new Dir (name: '/', dirs: [ new Dir (name: 'a'), Submission 631 © ASERT 2007 new Dir (name: 'b') ]) assert root.dirs[0].name == 'a' assert root.dirs.name == ['a', 'b'] assert root.dirs.name*.size() == [1, 1] def expected = ['getName', 'setName', 'getDirs', 'setDirs'] def accessorMethods = Dir.methods.name.grep(~/(g|s)et.*/) assert accessorMethods.intersect(expected) == expected // find, findAll, grep, every, any, … Agile 2007 - 36
  • 37. Static Imports Works with Java 1.4 import static java.awt.Color.LIGHT_GRAY Slightly more powerful import static Boolean.FALSE as F than Java equivalent import static Calendar.getInstance as now println LIGHT_GRAY // => java.awt.Color[r=192,g=192,b=192] println !F // => true println now().time // => Sun Apr 29 11:12:43 EST 2007 Submission 631 © ASERT 2007 import static Integer.* println quot;Integers are between $MIN_VALUE and $MAX_VALUEquot; // => Integers are between -2147483648 and 2147483647 def toHexString(int val, boolean upperCase) { def hexval = upperCase ? toHexString(val).toUpperCase() : toHexString(val) return '0x' + hexval } println toHexString(15, true) // => 0xF println toHexString(15, false) // => 0xf import static Math.* assert cos(2 * PI) == 1.0 Agile 2007 - 37
  • 38. Topics • Introduction • Language Basics Closures • Builders Submission 631 © ASERT 2007 • Data Access • Other Features • Testing with Groovy • Further Integration • Grails • More Information Agile 2007 - 38
  • 39. Using Closures... • Traditional mainstream languages – Data can be stored in variables, passed around, combined in structured ways to form more complex data; code stays put where it is defined • Languages supporting closures Submission 631 © ASERT 2007 – Data and code can be stored in variables, passed around, combined in structured ways to form more complex algorithms and data doubleNum = { num -> num * 2 } println doubleNum(3) // => 6 processThenPrint = { num, closure -> num = closure(num); println quot;num is $numquot; } processThenPrint(3, doubleNum) // => num is 6 processThenPrint(10) { it / 2 } // => num is 5 Agile 2007 - 39
  • 40. ...Using Closures... import static Math.* Algorithm piE differs by 1.0206946399193839E-11 Algorithm piF differs by 1.0070735356748628E-9 Algorithm piC differs by 2.668102068170697E-7 piA = { 22 / 7 } Algorithm piD differs by 4.813291008076703E-5 piB = { 333/106 } Algorithm piB differs by 8.321958979307098E-5 Algorithm piA differs by 0.001264489310206951 piC = { 355/113 } piD = { 0.6 * (3 + sqrt(5)) } piE = { 22/17 + 37/47 + 88/83 } piF = { sqrt(sqrt(2143/22)) } Submission 631 © ASERT 2007 howCloseToPI = { abs(it.value() - PI) } algorithms = [piA:piA, piB:piB, piC:piC, piD:piD, piE:piE, piF:piF] findBestPI(algorithms) def findBestPI(map) { map.entrySet().sort(howCloseToPI).each { entry -> def diff = howCloseToPI(entry) println quot;Algorithm $entry.key differs by $diffquot; } } Agile 2007 - 40
  • 41. ...Using Closures... • Used for many things in Groovy: • Iterators new File('/x.txt').eachLine { println it • Callbacks } • Higher-order functions • Specialized control structures Submission 631 © ASERT 2007 • Dynamic method definition • Resource allocation 3.times { println 'Hi' } • Threads [0, 1, 2].each { number -> • Continuations println number } def houston(Closure doit) { (10..1).each { count -> [0, 1, 2].each { println it} doit(count) def printit = { println it } } [0, 1, 2].each printit } houston { println it } Agile 2007 - 41
  • 42. ...Using Closures... map = ['a': 1, 'b': 2] map.each {key, value -> map[key] = value * 2} assert map == ['a': 2, 'b': 4] doubler = {key, value -> map[key] = value * 2} Submission 631 © ASERT 2007 map.each(doubler) assert map == ['a': 4, 'b': 8] def doubleMethod(entry) { map[entry.key] = entry.value * 2 } doubler = this.&doubleMethod map.each(doubler) assert map == ['a': 8, 'b': 16] Agile 2007 - 42
  • 43. ...Using Closures... assert [1, 2, 3].grep{ it < 3 } == [1, 2] assert [1, 2, 3].any{ it % 2 == 0 } assert [1, 2, 3].every{ it < 4 } assert (1..9).collect{it}.join() == '123456789' assert (1..4).collect{it * 2}.join() == '2468' Submission 631 © ASERT 2007 def add = { x, y -> x + y } def mult = { x, y -> x * y } assert add(1, 3) == 4 assert mult(1, 3) == 3 def min = { x, y -> [x, y].min() } def max = { x, y -> [x, y].max() } def triple = mult.curry(3); assert triple(2) == 6 def atLeastTen = max.curry(10) assert atLeastTen(5) == 10 assert atLeastTen(15) == 15 Agile 2007 - 43
  • 44. ...Using Closures def pairWise(list, Closure invoke) { if (list.size() < 2) return [] def next = invoke(list[0], list[1]) return [next] + pairWise(list[1..-1], invoke) } Submission 631 © ASERT 2007 // using min, max, etc. From previous slide assert pairWise(1..5, add) == [3, 5, 7, 9] assert pairWise(1..5, mult) == [2, 6, 12, 20] assert pairWise(1..5, min) == [1, 2, 3, 4] assert pairWise(1..5, max) == [2, 3, 4, 5] assert 'cbaxabc' == ['a', 'b', 'c'].inject('x') { result, item -> item + result + item } Agile 2007 - 44
  • 45. Topics • Introduction • Language Basics • Closures Builders Submission 631 © ASERT 2007 • Data Access • Other Features • Testing with Groovy • Further Integration • Grails • More Information Agile 2007 - 45
  • 46. Builder Pattern Inclusive • Builder pattern from the GoF at the syntax-level • Represents easily any nested tree-structured data import groovy.xml.* • Create new builder def page = new MarkupBuilder() Submission 631 © ASERT 2007 • Call pretended methods page.html { (html, head, ...) head { title 'Hello' } body { • Arguments are Closures ul { • Builder code looks very for (count in 1..10) { declarative but is ordinary li quot;world $countquot; }}}} Groovy program code and can contain any kind of NodeBuilder, DomBuilder, logic SwingBuilder, AntBuilder, … Agile 2007 - 46
  • 47. SwingBuilder import java.awt.FlowLayout builder = new groovy.swing.SwingBuilder() langs = [quot;Groovyquot;, quot;Rubyquot;, quot;Pythonquot;, quot;Pnutsquot;] gui = builder.frame(size: [290, 100], title: 'Swinging with Groovy!’) { panel(layout: new FlowLayout()) { panel(layout: new FlowLayout()) { Submission 631 © ASERT 2007 for (lang in langs) { checkBox(text: lang) } } button(text: 'Groovy Button', actionPerformed: { builder.optionPane(message: 'Indubitably Groovy!'). createDialog(null, 'Zen Message').show() }) button(text: 'Groovy Quit', actionPerformed: {System.exit(0)}) } } gui.show() Source: http://www.ibm.com/developerworks/java/library/j-pg04125/ Agile 2007 - 47
  • 48. AntBuilder def ant = new AntBuilder() ant.echo(quot;helloquot;) // lets just call one task // create a block of Ant using the builder pattern ant.sequential { myDir = quot;target/AntTest/quot; Submission 631 © ASERT 2007 mkdir(dir: myDir) copy(todir: myDir) { fileset(dir: quot;src/testquot;) { include(name: quot;**/*.groovyquot;) } } echo(quot;donequot;) } // now lets do some normal Groovy again file = new File(quot;target/test/AntTest.groovyquot;) assert file.exists() Agile 2007 - 48
  • 49. Using AntLibs: Maven Ant Tasks & AntUnit… def ant = new AntBuilder() items = [[groupId:'jfree', artifactId:'jfreechart', version:'1.0.5'], [groupId:'jfree', artifactId:'jcommon', version:'1.0.9']] def mvn = new AntLibHelper(ant:ant, namespace:'org.apache.maven.artifact.ant') def antunit = new AntLibHelper(ant:ant, namespace:'org.apache.ant.antunit') Submission 631 © ASERT 2007 // download artifacts with Maven Ant tasks mvn.dependencies(filesetId:'artifacts') { items.each{ dependency(it) } } // print out what we downloaded ant.fileScanner { fileset(refid:'artifacts') }.each { println it } // use AntUnit to confirm expected files were downloaded def prefix = System.properties.'user.home' + '/.m2/repository' items.each { item -> def g = item.groupId def a = item.artifactId def v = item.version antunit.assertFileExists(file:quot;$prefix/$g/$a/$v/$a-${v}.jarquot;) } Agile 2007 - 49
  • 50. …Using AntLibs: Maven Ant Tasks & AntUnit ... class AntLibHelper { def namespace, ant Object invokeMethod(String name, Object params) { ant.quot;antlib:$namespace:$namequot;(*params) } } Submission 631 © ASERT 2007 /* => Downloading: jfree/jfreechart/1.0.5/jfreechart-1.0.5.pom Transferring 1K Downloading: jfree/jcommon/1.0.9/jcommon-1.0.9.pom Transferring 1K Downloading: jfree/jfreechart/1.0.5/jfreechart-1.0.5.jar Transferring 1157K Downloading: jfree/jcommon/1.0.9/jcommon-1.0.9.jar Transferring 298K C:UsersPaul.m2repositoryjfreejcommon1.0.9jcommon-1.0.9.jar C:UsersPaul.m2repositoryjfreejfreechart1.0.5jfreechart-1.0.5.jar */ Agile 2007 - 50
  • 51. Topics • Introduction • Language Basics • Closures • Builders Data Access Submission 631 © ASERT 2007  Objects  XML  Databases • Other Features • Testing with Groovy • Further Integration • Grails • More Information Agile 2007 - 51
  • 52. Uniform Data Access • Data Access to Objects, XML, SQL Databases has some differences and some similarities – Differences in detail about how to set up structures – Similarities in how to process data within resulting Submission 631 © ASERT 2007 structures Agile 2007 - 52
  • 53. Object Data Access… import java.text.SimpleDateFormat class Athlete { def firstname, lastname, gender, country, dateOfBirth } def asDate(dateStr) { new SimpleDateFormat(quot;yyyy-MM-ddquot;).parse(dateStr) Submission 631 © ASERT 2007 } def athletes = [ new Athlete(firstname: 'Paul', lastname: 'Tergat', dateOfBirth: '1969-06-17', gender: 'M', country: 'KEN'), new Athlete(firstname: 'Khalid', lastname: 'Khannouchi', dateOfBirth: '1971-12-22', gender: 'M', country: 'USA'), new Athlete(firstname: 'Sammy', lastname: 'Korir', dateOfBirth: '1971-12-12', gender: 'M', country: 'KEN'), new Athlete(firstname: 'Ronaldo', lastname: 'da Costa', dateOfBirth: '1970-06-07', gender: 'M', country: 'BRA'), new Athlete(firstname: 'Paula', lastname: 'Radcliffe', dateOfBirth: '1973-12-17', gender: 'F', country: 'GBR') ] Agile 2007 - 53
  • 54. …Object Data Access def bornSince70 = { asDate(it.dateOfBirth) > asDate('1970-1-1') } def excludingKh = { it.lastname <= 'Kg' || it.lastname >= 'Ki' } def byGenderDescThenByCountry = { a, b -> a.gender == b.gender ? Submission 631 © ASERT 2007 a.country <=> b.country : b.gender <=> a.gender } def someYoungsters = athletes. findAll(bornSince70). findAll(excludingKh). sort(byGenderDescThenByCountry) someYoungsters.each { def name = quot;$it.firstname $it.lastnamequot;.padRight(25) println quot;$name ($it.gender) $it.country $it.dateOfBirthquot; } Agile 2007 - 54
  • 55. Xml Data Access… import java.text.SimpleDateFormat import com.thoughtworks.xstream.XStream class Athlete { String firstname, lastname, gender, country, dateOfBirth } def asDate(dateStr) { new SimpleDateFormat(quot;yyyy-MM-ddquot;).parse(dateStr) } Submission 631 © ASERT 2007 def athleteList = [ new Athlete(firstname: 'Paul', lastname: 'Tergat‘, dateOfBirth: '1969-06-17', gender: 'M', country: 'KEN'), new Athlete(firstname: 'Khalid', lastname: 'Khannouchi', dateOfBirth: '1971-12-22', gender: 'M', country: 'USA'), new Athlete(firstname: 'Sammy', lastname: 'Korir', dateOfBirth: '1971-12-12', gender: 'M', country: 'KEN'), new Athlete(firstname: 'Ronaldo', lastname: 'da Costa', dateOfBirth: '1970-06-07', gender: 'M', country: 'BRA'), new Athlete(firstname: 'Paula', lastname: 'Radcliffe', dateOfBirth: '1973-12-17', gender: 'F', country: 'GBR') ] // create XML as input def input = new XStream().toXML(athleteList) Agile 2007 - 55
  • 56. …Xml Data Access def athletes = new XmlSlurper().parseText(input).Athlete def bornSince70 = { asDate(it.dateOfBirth.text()) > asDate('1970-1-1') } def excludingKh = { it.lastname.text() <= 'Kg' || it.lastname.text() >= 'Ki' } def byGenderDescThenByCountry = { a, b -> Submission 631 © ASERT 2007 a.gender.text() == b.gender.text() ? a.country.text() <=> b.country.text() : b.gender.text() <=> a.gender.text() } def someYoungsters = athletes. findAll(bornSince70).findAll(excludingKh).list(). sort(byGenderDescThenByCountry) someYoungsters.each { def name = quot;$it.firstname $it.lastnamequot;.padRight(25) println quot;$name ($it.gender) $it.country $it.dateOfBirthquot; } Agile 2007 - 56
  • 57. Sql Data Access… import groovy.sql.Sql dbHandle = null def getDb() { if (dbHandle) return dbHandle def source = new org.hsqldb.jdbc.jdbcDataSource() source.database = 'jdbc:hsqldb:mem:GIA' source.user = 'sa' source.password = '' Submission 631 © ASERT 2007 dbHandle = new Sql(source) return dbHandle } db.execute ''' DROP INDEX athleteIdx IF EXISTS; DROP TABLE Athlete IF EXISTS; CREATE TABLE Athlete ( athleteId INTEGER GENERATED BY DEFAULT AS IDENTITY, firstname VARCHAR(64), lastname VARCHAR(64), country VARCHAR(3), gender CHAR(1), dateOfBirth DATE ); CREATE INDEX athleteIdx ON Athlete (athleteId); ''' Agile 2007 - 57
  • 58. …Sql Data Access… def athleteList = [ [firstname: 'Paul', lastname: 'Tergat', dateOfBirth: '1969-06-17', gender: 'M', country: 'KEN'], [firstname: 'Khalid', lastname: 'Khannouchi', dateOfBirth: '1971-12-22', gender: 'M', country: 'USA'], [firstname: 'Sammy', lastname: 'Korir', Submission 631 © ASERT 2007 dateOfBirth: '1971-12-12', gender: 'M', country: 'KEN'], [firstname: 'Ronaldo', lastname: 'da Costa', dateOfBirth: '1970-06-07', gender: 'M', country: 'BRA'], [firstname: 'Paula', lastname: 'Radcliffe', dateOfBirth: '1973-12-17', gender: 'F', country: 'GBR'] ] def athletes = db.dataSet('Athlete') athleteList.each {a -> athletes.add(a)} Agile 2007 - 58
  • 59. …Sql Data Access def bornSince70 = { it.dateOfBirth > '1970-1-1' } def excludingKh = { it.lastname <= 'Kg' || it.lastname >= 'Ki' } def someYoungsters = athletes. findAll(bornSince70). findAll(excludingKh). sort { it.gender }.reverse(). // * experimental sort { it.country } // * experimental Submission 631 © ASERT 2007 println someYoungsters.sql + 'n' + someYoungsters.parameters someYoungsters.each { def name = quot;$it.firstname $it.lastnamequot;.padRight(25) println quot;$name ($it.gender) $it.country $it.dateOfBirthquot; } /* => select * from Athlete where dateOfBirth > ? and (lastname <= ? or lastname >= ?) order by gender DESC, country [quot;1970-1-1quot;, quot;Kgquot;, quot;Kiquot;] Ronaldo da Costa (M) BRA 1970-06-07 Sammy Korir (M) KEN 1971-12-12 Paula Radcliffe (F) GBR 1973-12-17 */ Agile 2007 - 59
  • 60. More Details: XmlSlurper… • Features – One-line parsing – GPath Syntax – Efficient lazy evaluation static def CAR_RECORDS = ''' Submission 631 © ASERT 2007 <records> <car name='HSV Maloo' make='Holden' year='2006'> <country>Australia</country> <record type='speed'>Production Pickup Truck with speed of 271kph</record> </car> <car name='P50' make='Peel' year='1962'> <country>Isle of Man</country> <record type='size'>Smallest Street-Legal Car at 99cm wide and 59 kg in weight</record> </car> <car name='Royale' make='Bugatti' year='1931'> <country>France</country> <record type='price'>Most Valuable Car at $15 million</record> </car> </records> ''' Agile 2007 - 60
  • 61. …More Details: XmlSlurper def records = new XmlSlurper().parseText(XmlExamples.CAR_RECORDS) // 3 records in total assert 3 == records.car.size() // 10 nested nodes assert 10 == records.depthFirst().collect{ it }.size() // test properties of the first record def firstRecord = records.car[0] assert 'car' == firstRecord.name() assert 'Holden' == firstRecord.@make.toString() assert 'Australia' == firstRecord.country.text() Submission 631 © ASERT 2007 // 2 cars have an 'e' in the make assert 2 == records.car.findAll{ it.@make.toString().contains('e') }.size() // 2 cars have an 'e' in the make assert 2 == records.car.findAll{ it.@make =~ '.*e.*' }.size() // makes of cars that have an 's' followed by an 'a' in the country assert ['Holden', 'Peel'] == records.car.findAll{ it.country =~ '.*s.*a.*' }.@make.collect{ it.toString // types of records assert ['speed', 'size', 'price'] == records.depthFirst().grep{ it.@type != '' }.'@type'*.toString() assert ['speed', 'size', 'price'] == records.'**'.grep{ it.@type != '' }.'@type'*.toString() // check parent() operator def countryOne = records.car[1].country assert 'Peel' == countryOne.parent().@make.toString() assert 'Peel' == countryOne.'..'.@make.toString() // names of cars with records sorted by year def names = records.car.list().sort{ it.@year.toInteger() }.'@name'*.toString() assert ['Royale', 'P50', 'HSV Maloo'] == names Agile 2007 - 61
  • 62. More Details: Working with Databases • Using standard SQL statements import groovy.sql.Sql def foo = 'cheese' def sql = Sql.newInstance(quot;jdbc:mysql://localhost:3306/mydbquot;, quot;userquot;, quot;pswdquot;, quot;com.mysql.jdbc.Driverquot;) sql.eachRow(quot;select * from FOOD where type=${foo}quot;) { Submission 631 © ASERT 2007 println quot;Gromit likes ${it.name}quot; } • Using DataSets import groovy.sql.Sql def sql = Sql.newInstance(quot;jdbc:mysql://localhost:3306/mydbquot;, quot;userquot;, quot;pswdquot;, quot;com.mysql.jdbc.Driverquot;) def food = sql.dataSet('FOOD') def cheese = food.findAll { it.type == 'cheese' } cheese.each { println quot;Eat ${it.name}quot; } Agile 2007 - 62
  • 63. DataSets and Lazy Evaluation athleteSet = db.dataSet('Athlete') youngsters = athleteSet.findAll{ it.dateOfBirth > '1970-1-1'} paula = youngsters.findAll{ it.firstname == 'Paula'} println paula.sql // => Submission 631 © ASERT 2007 // select * from Athlete where dateOfBirth > ? and firstname = ? println paula.parameters // => // [1970-1-1, Paula] paula.each { println it.lastname } // database called here // => // Radcliffe Agile 2007 - 63
  • 64. Topics • Introduction • Language Basics • Closures • Builders Submission 631 © ASERT 2007 • Data Access Other Features • Testing with Groovy • Further Integration • Grails • More Information Agile 2007 - 64
  • 65. JMX import javax.management.remote.* import javax.management.* import javax.naming.Context def urlRuntime = '/jndi/weblogic.management.mbeanservers.runtime' def urlBase = 'service:jmx:t3://localhost:7001' def serviceURL = new JMXServiceURL(urlBase + urlRuntime) def h = new Hashtable() h.put(Context.SECURITY_PRINCIPAL, 'weblogic') Submission 631 © ASERT 2007 h.put(Context.SECURITY_CREDENTIALS, 'weblogic') h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, 'weblogic.management.remote') def server = JMXConnectorFactory.connect(serviceURL, h).mBeanServerConnection def domainName = new ObjectName('com.bea:Name=RuntimeService,' + 'Type=weblogic.management.mbeanservers.runtime.RuntimeServiceMBean') def rtName = server.getAttribute(domainName, 'ServerRuntime') def rt = new GroovyMBean(server, rtName) println quot;Server: name=$rt.Name, state=$rt.State, version=$rt.WeblogicVersionquot; def destFilter = Query.match(Query.attr('Type'), Query.value( 'JMSDestinationRuntime')) server.queryNames(new ObjectName('com.bea:*'), destFilter).each {name -> def jms = new GroovyMBean(server, name) println quot;JMS Destination: name=$jms.Name, type=$jms.DestinationTypequot; + quot;, messages=$jms.MessagesReceivedCountquot; } Agile 2007 - 65
  • 66. ExpandoMetaClass… String.metaClass.swapCase = {-> def sb = new StringBuffer() delegate.each { sb << (Character.isUpperCase(it as char) ? Character.toLowerCase(it as char) : Character.toUpperCase(it as char)) } Submission 631 © ASERT 2007 sb.toString() } List.metaClass.sizeDoubled = {-> delegate.size() * 2 } LinkedList list = [] list << 1 list << 2 assert 4 == list.sizeDoubled() Agile 2007 - 66
  • 67. …ExpandoMetaClass class Person { String name } class MortgageLender { def borrowMoney() { quot;buy housequot; Submission 631 © ASERT 2007 } } def lender = new MortgageLender() Person.metaClass.buyHouse = lender.&borrowMoney def p = new Person() assert quot;buy housequot; == p.buyHouse() Agile 2007 - 67