Showing posts with label Groovy. Show all posts
Showing posts with label Groovy. Show all posts

Saturday, May 2, 2015

Groovy's powerful collection methods

Recently I just realize Groovy provides some handy methods for collections.

Permutations

Combinations

Subsequences
Intersect

Wednesday, April 29, 2015

Regular expression: you should not use dot to match any character in Java/Groovy

Recently I just realize that in if you want to match "any character" in  Java/Groovy, you should not use dot match (.).

The reason is: dot match only works for single line text, will not work for line breaks.  For the multiple lines text matching, the solution to match any character is using [\s\S].

Please refer this article for details.

For example, following code snippet is used for stripping the javascript code in the text

Source code:

Thursday, July 10, 2014

Using Groovy MarkupBuilder to generate XML Declaration and DOCTYPE

I found Groovy MarkupBuilder can also generate xml declaraion and doctype, with the help of groovy.xml.MarkupBuilderHelper class. Following is the example

def sw = new StringWriter()
def xml = new groovy.xml.MarkupBuilder(sw)

def helper = new groovy.xml.MarkupBuilderHelper(xml)
helper.xmlDeclaration([version:'1.0', encoding:'UTF-8', standalone:'no'])
helper.yieldUnescaped """<!DOCTYPE note SYSTEM "note.dtd">
"""

xml.person{
  firstname("Steve")
  lastname("Zhang")
  country("Canada")
  city("Toronto")
}

println sw.toString()


And the result:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE note SYSTEM "note.dtd">
<person>
  <firstname>Steve</firstname>
  <lastname>Zhang</lastname>
  <country>Canada</country>
  <city>Toronto</city>
</person>

Monday, February 13, 2012

Using Groovy to update/generate XML file


Recently when I refactored the Android framework in my work, I found I need to generate eclipse .classpath file based on the library file.
I found using Groovy XML library is a lot easier to do this job compare to Java.

1. Add a new library to the current .classpath file.
Problem:  You have a Eclipse .classpath file, which is XML, you need to add another jar file in the class path. for example, adding following into the .classpath:
Solution:
 If you want to write the output to file, use the following code snippet:

There is another method to print XML, using XmlNodePrinter, like:
But I found using XmlNodePrinter will not generate line break, and no xml header either.

2. Generate a new .classpath file
Problem:  iterate the libs folder, add all the jar file name into the .classpath file.
Solution:

Friday, April 22, 2011

Invoke Groovy script from Ant or Gant

Recently I tried to use groovy script to improve our build system. I found Groovy TemplateEngine is so powerful and very easy to use, quite similar to erb in Ruby. I want to use it to generate a text file. The following example shows how to generate a text file based on a template.

file test.template
Dear "$firstname $lastname",
So nice to meet you in <% out << (city == "New York" ? "\"The Big Apple\"" : city) %>.

file test.groovy
import groovy.text.SimpleTemplateEngine
import groovy.text.GStringTemplateEngine

def f = new File(this.args[0])
def binding = ["firstname":args[1], "lastname":args[2], "city":args[3]]
engine = new GStringTemplateEngine()
template = engine.createTemplate(f).make(binding)
println template.toString()


If in a terminal if I type:  groovy test.groovy Steve Zhang Toronto, and I will get output

Dear "Steve Zhang",
So nice to meet you in Toronto.

Invoke Groovy from Ant
I followed this article from Groovy site
Following is the ant script:
build.xml
<project>
 <taskdef name="groovy"
          classname="org.codehaus.groovy.ant.Groovy"
          classpath="lib/groovy-all-1.7.10.jar"/>
 
 <target name="helloGroovy">
    <groovy>
     println "hello world"
    </groovy>
 </target>
   
    <target name="testTemplate">
   <groovy src="test.groovy">
    <arg line="test.template"/>
    <arg line="Steve" />
    <arg line="Zhang"/>
    <arg line="Toronto"/>
    </groovy>
 </target> 
</project>
It pretty straight forward, first declare <taskdef>, you need to put groovy-all-version.jar in the class path, but it took me a while to figure out where the groovy-all-xxx.jar is, finally I got it: when you download the binary zip file, unzip it, find embeddable folder, inside this folder you will find the groovy-all-1.7.x.jar!
Then you can put any kind of groovy code inside <groovy>.

Invoke Groovy Script from Gant
Gant is a great tool to replace Ant, I can definitely convert the above build.xml to build.gant, but I realize it is a kind of weird, since Gant is already based on Groovy, it already depends on Groovy jars, why we still need to declare the dependency in groovy-all-xxx.jar? There must be a better solution. Through my exploration, I found two ways to call Groovy script from Gant:

A) Use GroovyShell
target( runGroovy:"run a groovy script") {
 def shell = new GroovyShell()
    shell.run(new File("test.groovy"),
               ["test.template","Steve","Zhang","Toronto"] as String[])
    
}

The above gant script also tells you how to invoke a groovy script from another Groovy script file. GroovyShell can do this for us.

B) Embed the groovy source code directly in the Gant script file
During the exploration, I have some feeling that Gant script might can be thought of Groovy code, what if we add the groovy source code directly into the Gant script, so I did this:
import groovy.text.GStringTemplateEngine

target( hello: "hello") {
  println "hello"
}

target( runGroovy:"run a groovy script") {
 def shell = new GroovyShell()
    shell.run(new File("test.groovy"),
               ["test.template","Steve","Zhang","Toronto"] as String[])
    
}

target(runTemplate :"run a groovy template") {
 def f = new File('test.template')
 def binding = ["firstname":"Steve", "lastname":"Zhang", "city":"Toronto"]
 engine = new GStringTemplateEngine()
 template = engine.createTemplate(f).make(binding)
    println template.toString()
}
The target runTemplate will have the same result output, when you look at the import statement at the top, and the groovy code inside the target, I realize that Gant script is actually Groovy code!, the Gant target can be regarded as Groovy method. This conclusion is so important, because it means you can easily integrate the Groovy(or Java) code in the build script, I am sure it will definitely improve developer's productivity.

Tuesday, December 28, 2010

The power of Groovy - notes of "Transforming to Groovy"

Yesterday I watched a video presentation from infoQ:"Transforming to Groovy", presented by Venkat Subramaniam, I read his book: Programming Groovy. The presentation is really great, the author used lots of code examples to explain the power of groovy: first he provided the java code, then refactored it into groovy code, so you will find out how concise the Groovy is compare to Java. The whole presentation is 1.5 hour, but I did not feel it is quite long.  I remembered the author describe the Groovy using the term "less ceremony", Which reminds me the how to describe the power of Groovy: "Accomplish more by doing less". And when he refactored java code to Groovy code, he described it as "reducing the noise".  I like the word "noise" to describe Java code, since Groovy is quite expressive, concise, and its dynamic nature allow developer to focus more on their core business problems ( essential problem), and spend less time to deal with the language issues (accidental problem), which is noise compare to the business problem.

What I learned
AST transformation
   Before I did not aware the feature of AST transformation in Groovy, probably this is the new feature,  because I did not find this topic in the book.
  The author covered @Immutable, @Newify, and @Delegate

@Immutable
@Immutable class Person {
   String firstName;
   String lastName;
   int age;
}
@Immutable annotation applies to class level only, it does not support on the field level.

@Newify
@Newify def createPerson {
    Person.new("John", "Smith", 28)
}

@Newify(Person)
def createPerson {
   Person("John", "Smith", 28)
}

@Delegate
class TirelessWorker {
   public void work() {}
   public void report() {}
}

class Manager {
   @Delegate employee = new TirelessWorker();
   public void schedule() {}
}

Here the Manager class can use all the methods of TirelessWorker class, if you add/modify method of class Tirelessworker, you don't have to modify the Manager class, it follows the OCP principle.

Multimethods
Multimethods is one of the major difference between Groovy and Java. Multimethod means the method call depends on the target and the parameter type, which reminds me the multiple dispatch, Java does not support mutlimethod, it only support single dispatch, I remember when I learn the Visitor pattern, I learned the multiple dispatch term, I am sure the Visitor pattern will be much easier to understand if the language support multiple dispatch, cool.

ArrayList
use spread-dot operator to access ArrayList
*.  is called spread-dot operator, for example:
list*.member  =  list.collect { item -> item?.member }

It means given a list, iterate each item's specific method, form the return value as a collection.
get each item's first name: list*.firstName

Groovy follows the Kanban principle
I think Groovy is a good example of evolutionary and emergent design, since you can begin with purely java code, then migrate with Groovy, and even more you can mix with java and Groovy code in your project. Let's look at the Kanban's 2 foundational principles: Start with what you do now; Agree to pursue incremental, evolutionary change. Pretty similar.

Based on this, I think Groovy is an important language that worth every Java developer to looking at.

Saturday, October 16, 2010

Gant Script: print ant default properties

If you want to know exactly what kind of ant properties in your environment, try the following gant target:

target(properties : "print ant default properties") {
     println "ant properties are:"
     ant.project.properties.each { key, value ->
         println "${key} = ${value}"
     }
}

Here are some of the out put:
ant properties are:
ant.version = Apache Ant version 1.8.1 compiled on April 30 2010
sun.os.patch.level = unknown
java.vm.vendor = Apple Inc.
environment.HOME = /Users/steve
environment.TERM_PROGRAM = Apple_Terminal
file.encoding = MacRoman
user.language = en
java.class.path = /opt/local/share/java/gant/lib/groovy-all-1.7.3.jar
file.separator = /
java.runtime.name = Java(TM) SE Runtime Environment
basedir = /Users/steve/dev/gant
java.vm.specification.version = 1.0
awt.nativeDoubleBuffering = true

...
...

Look how easy it work in the Groovy/Gant script, I am sure it is much harder to write in ant xml build script, and you have to use ant-contrib to implement the for loop!  Byebye XML!

Build J2ME app using Gant

These days I spent some time learning Groovy. Why I learn Groovy? Because I want to use Gant.  Gant = Groovy + Ant. Gant is really powerful, since you can use Groovy script and Ant API to write your build script instead of XML. I struggle a long time in Ant, because I have to use Ant-Contrib plugin, and it is so hard to write an condition block and even for loop,  it is much easier to do that in Gant script.

Now I am going to share the gant script of building J2ME app, this is just basic, but you can see the power of Gant.

Requirement:
1. You need to install Groovy and Gant, here is the link, I used 1.9.3 in Mac.
2. download the latest version of antenna, here is the download link,  I used 1.2.1-beta.
3. install the JavaME SDK,  I choose  JavaME SDK 3, since it works on Mac.

The J2ME MIDlet class source code:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class HelloWorld extends MIDlet implements CommandListener {
    private final Command exitCommand;
    private final Form form;
 
    public HelloWorld() {
        exitCommand = new Command("Exit", Command.EXIT, 1);
        form = new Form("Hello World!");
        form.append("from Steve");
        form.addCommand(exitCommand);
        form.setCommandListener(this);
    }
 
    protected void startApp() {
        Display.getDisplay(this).setCurrent(form);
    }
 
    protected void pauseApp() {}
    protected void destroyApp(boolean force) {}
 
    public void commandAction(Command cmd, Displayable disp) {
        if (cmd == exitCommand) {
            destroyApp(false);
            notifyDestroyed();
        }
    }
}

The Ant script looks like:

<project name="antenna-test" default="jar" basedir=".">
 
 <taskdef resource="antenna.properties" classpath="./antenna-bin-1.2.1-beta.jar" />
 
 <property name="wtk.home" value="/Users/Steve/dev/wtk252" />
 <property name="wtk.midp.version" value="2.0" />
 <property name="wtk.cldc.version" value="1.1" />
 
 <property name="src.dir" location="src" />
 <property name="out.dir" location="out" />
 <property name="dist.dir" location="dist" />
 <property name="preverified.dir" location="preverified" />
  
 <!-- Regular targets -->
 <target name="clean" description="cleans the target directory">
  <delete dir="${out.dir}"/>
  <delete dir="${dist.dir}"/>
  <delete dir="${preverified.dir}"/>
 </target>
 
 <target name="compile" depends="init">
  <wtkbuild source="1.3" srcdir="${src.dir}" destdir="${out.dir}">
  </wtkbuild>
 </target>
 
 
 <target name="preverify" depends="compile">
  <wtkpreverify srcdir="${out.dir}" destdir="${preverified.dir}">
  </wtkpreverify>
 </target>
 
 <target name="jar" depends="compile,jad,preverify">
  <wtkpackage jarfile="${dist.dir}/helloworld.jar"
                      jadfile="${dist.dir}/helloworld.jad"
                      obfuscate="false"
                      preverify="false">

       <fileset dir="${out.dir}"/>
        </wtkpackage>
   
 </target>
 
 <target name="jad" depends="compile">
  <wtkjad  version="0.01" name="hello" vendor="foo" jadfile="${dist.dir}/helloworld.jad" jarfile="${dist.dir}/helloworld.jar">
    <midlet name="hello" class="HelloWorld">
    </midlet> 
  </wtkjad>
 </target> 
 <target name="init" description="initialization for properties and paths" depends="clean">
  <buildnumber/>
  <mkdir dir="${out.dir}"/>
  <mkdir dir="${dist.dir}"/>
  <mkdir dir="${preverified.dir}" />
 </target>
 
 
</project>

the build script build.gant:

ant.taskdef(resource:"antenna.properties", classpath:"./antenna-bin-1.2.1-beta.jar")

ant.property(name:"wtk.home", value:"/Applications/Java_ME_SDK_3.0.app/Contents/Resources")
ant.property(name:"wtk.midp.version", value:"2.0")
ant.property(name:"wtk.cldc.version", value:"1.1")

final srcDir = "src"
final outDir = 'out'
final distDir = 'dist'
final preverifiedDir = 'preverified'

//clean target
includeTargets << gant.targets.Clean
cleanPattern << '**/*~'
cleanDirectory << [ outDir, distDir, preverifiedDir]


target(name:"init", description:"initialization") {
 depends(clean)
 /*buildnumber() */
 mkdir(dir:outDir)
 mkdir(dir:distDir)
 mkdir(dir:preverifiedDir)
}

target(name:"compile", description:"compile") {
 depends(init)
 wtkbuild( source:"1.3", srcdir:srcDir, destdir:outDir)
}

target(name:"preverify", description:"preverify") {
 depends(compile)
 wtkpreverify(srcdir:outDir, destdir:preverifiedDir)
}

//target jad file

target(name:"jad", description:"generate jad file") {
    depends(compile)
 wtkjad( version:"0.01", name:'hello', vendor:"foo", jadfile:"${distDir}/helloworld.jad", jarfile:"${distDir}/helloworld.jar" ) {
  midlet(name:"hello", class:"HelloWorld")
 }
}

//target jar
target(name:"jar", description:"generating jar file") {
 depends(compile,jad)
 wtkpackage( jadfile:"${distDir}/helloworld.jad", jarfile:"${distDir}/helloworld.jar", obfuscate:"false", preverify:"false")  {
  fileset(dir:outDir)
 }
}

//target obfuscate

//target all
target(name:"all", description: "build the whole app") {
 depends(jar)
}

setDefaultTarget(all)



From the above script, you can see how easy to write gant build script.
This is only the basic implementation, I am going to post more Gant based script in future.

In future I am going to consider:
1. How to integrate with ANT script;
2. How import multiple Gant script file.