Showing posts with label groovy. Show all posts
Showing posts with label groovy. Show all posts

Saturday, June 08, 2013

How to calculate MD5 as zero-padded hex string in Groovy?

import java.security.MessageDigest
 
def digest = MessageDigest.getInstance("MD5")
 
def bytes = data.getBytes()
def md5 = digest.digest(bytes)
 
// Convert to hex, left-padded with 0 to 32 chars
def hex = new BigInteger(1, md5).toString(16).padLeft(32, "0")

Gist: https://gist.github.com/sjtai/5733901

Saturday, May 02, 2009

Self-printing Groovy Program

It always amazes me when I read about how people write a C program that print itself. The self-printing program, or more formally, quine, prints out its source code.

Having used Groovy for a while, I wonder if there is any self-printing Groovy program on the Internet. After some googling around, I found some Java programs on this page. After spending about 15 minutes, I came up with what I think is the first self-printing Groovy program to date. I used Bertram Felgenhauer's 2nd example as my starting point. Here is my version in Groovy (the code is written in one line):

class S{public static void main(a){def s="class S{public static void main(a){def s=;char c=34;println(s.substring(0,41)+c+s+c+s.substring(41));}}";char c=34;println(s.substring(0,41)+c+s+c+s.substring(41));}}

See if you can make it shorter.

Updates



Chrigel suggested the removal of "public". I have to adjust the parameter to substring() too. Here is a shorter version (195 bytes):

class S{static void main(a){def s="class S{static void main(a){def s=;char c=34;println(s.substring(0,34)+c+s+c+s.substring(34));}}";char c=34;println(s.substring(0,34)+c+s+c+s.substring(34));}}


paulk's version is 97 bytes:

def s="def s=;char c=34;println s[0..5]+c+s+c+s[6..-1]";char c=34;println s[0..5]+c+s+c+s[6..-1]


paulk's 2nd version is 46 bytes:

s="s=%c%s%c;printf s,34,s,34";printf s,34,s,34


paulk's 3rd version is 42 bytes. Keep going, paulk!

s='s=%c%s%1$c;printf s,39,s';printf s,39,s


Gavin Grover found a 38-char solution at http://golf.shinh.org/p.rb?Quine:

printf _='printf _=%c%s%1$c,39,_',39,_


Are we approaching the limit?

Wednesday, April 15, 2009

Groovy's groupBy and inject methods

groupBy



Aman Aggarwal blogged about a powerful method from the java.util.Collection class. The groupBy method converts a collection into a Map with the keys being returned by the closure passed to the method.

Example:

def map = invoices.groupBy { it.invoiceDate.format("MM/yyyy") }
map.each { k, v ->
println "There are ${v.size()} invoices in ${k}"
}


Incidentally, the example above uses another cool function from java.util.Date: format. The method takes a date pattern (from the specification of java.text.SimpleDateFormat) and returns a String.

inject



While writing about groupBy, I thought I might as well talk about the inject() method too. It is a method that is best explained with an example. If I want to add all the numbers from 1 until 10, i.e. 1 + 2 + 3 + 4 + ... + 10, I can do it in one line:

def sum = (1..10).inject(0) { a, b -> a += b }

0 is passed as the initial value. In each iteration, the value from the last iteration is passed as a while the current value is passed as b. If we add a println statement, e.g.

def sum = (1..10).inject(0) { a, b ->
println "${a} + ${b} = ${a + b}"
a += b
}

The output will be:

0 + 1 = 1
1 + 2 = 3
3 + 3 = 6
6 + 4 = 10
10 + 5 = 15
15 + 6 = 21
21 + 7 = 28
28 + 8 = 36
36 + 9 = 45
45 + 10 = 55


Another typical example is to calculate the product of a range of numbers. For example, to calculate the product of 1 to 10 (the factorial of 10):

def product = (1..10).inject(1) { a, b -> a *= b }


The result is the expected 3628800 (= 10!).

Friday, April 10, 2009

New find and findAll methods for String in Groovy 1.6.1

In Ted Naleid's blog, he describes the patches to the String class that he contributed to the Groovy community recently. The patches have been released as Groovy 1.6.1 on April 7, 2009.

He listed the following new methods:

  • eachMatch(Pattern pattern) { fullMatch, group1, ... -> ... }

  • find(String regex)

  • find(String regex) { fullMatch, group1, ... -> ... }

  • find(Pattern pattern)

  • find(Pattern pattern) { fullMatch, group1, ... -> ... }

  • findAll(String regex)

  • findAll(String regex) { fullMatch, group1, ... -> ... }

  • findAll(Pattern pattern)

  • findAll(Pattern pattern) { fullMatch, group1, ... -> ... }


In other words, the find/findAll methods now accepts a regular expression and the matching groups are passed to the closure.

Thanks for the patches, Ted.

Thursday, March 12, 2009

Groovy wrapper for Snipplr API

I created a Groovy wrapper for Snipplr API this afternoon. It is called, rather boringly, gsnipplr. I wanted to try out Groovy's XMLRPC module and use Maven to build the Groovy project. I threw in quite a comprehensive set of tests (IMO) and had a lot of fun playing with the testing code.

A lot of ideas were taken from arcturus' SnipplrPy. Thanks for the great example!

The source code is hosted at http://bitbucket.org/sjtai/gsnipplr.

To check out:

hg clone http://bitbucket.org/sjtai/gsnipplr

Friday, February 13, 2009

Shell Script in Groovy

It is possible to write a shell script using groovy. To do that, just write the script in a text editor, but remember to add the shebang line. For example, the following script will print "Hello World", groovy style:

#!/usr/bin/env groovy
println "Hello World"


The script can be named anything. It doesn't have to end with .groovy. Caveat: the script will not work if groovy is not in the PATH.

Monday, December 29, 2008

XmlParser trim whitespace by default

I just found out that groovy.util.XmlParser trims whitespace by default. When parsing XML files with text nodes that contain trailing whitespace, for example, whitespace is removed in the Node returned by the parser.

def parser = new XmlParser()
def doc = parser.parseText("ABC ")
assert doc.data.text() == "ABC" // Not "ABC "!


To preserve whitespace, set the trimWhitespace property to false:

def parser = new XmlParser(trimWhitespace: false)
def doc = parser.parseText("ABC ")
assert doc.data.text() == "ABC "

Thursday, July 24, 2008

Adding jar to classpath at run time

Whenever I want to test some groovy ideas, I use groovyConsole. However, I don't want to copy the dependent jar files into my $HOME/.groovy/lib, and as of groovy 1.5.6, it is still not possible to add -classpath to the command line of groovyConsole.bat.

I found a solution on the web. Just add this line into the start of the code:

this.getClass().classLoader.rootLoader.addURL(new File("file.jar").toURL())


Better still, use a list:

[ "file1.jar", "file2.jar" ].each {
this.getClass().classLoader.rootLoader.addURL(new File(it).toURL())
}

Wednesday, March 19, 2008

Create recursive markup with MarkupBuilder

I just found a way use Groovy's MarkupBuilder to build an XML file with nested elements. Assuming I have a container with a collection of X objects and a Y object. The XML output of the container can be generated as follows:

import groovy.xml.*

class X {
private int id
private String name

def toXML = { builder ->
builder.x(id: id, name)
}
}

class Y {
private Date date = new Date()
def toXML = { builder ->
final sdf = new java.text.SimpleDateFormat("yyyyMMdd'T'HH:mm:ssZ")
builder.y(date: sdf.format(date))
}
}

def w = new StringWriter()
def xml = new MarkupBuilder(w)
xml.doubleQuotes = true
def xa = [ new X(id: 1, name: "x-name"), new X(id: 2, name: 'x-name2') ]
def yObj = new Y()
xml.root() {
agent(id: 1, name: 'agent1', "X")
xa.each { xo ->
xo.toXML(xml)
}
yObj.toXML(xml)
}
w.close()

The variable w is equivalent to:

<root>
<agent id="1" name="agent1">X</agent>
<x id="1">x-name</x>
<x id="2">x-name2</x>
<y date="20080318T23:56:54+0800" />
</root>

Notice that to get the builder to output double quotes for attributes, I set the doubleQuotes property to true.


Tuesday, November 20, 2007

Reverse engineer the ER diagram

In every single project that I have been involved in, there is also a need to generate the ER diagram from the database. There are tools to do the reverse-engineering part. However, I have not come across a tool (and free one) that can rearrange the rectangles nicely.

Out of frustration, I wrote a script in Groovy to generate GraphML file from the DB schema.

The script gets a java.sql.Connection and use the DatabaseMetaData to find out the dependencies of the tables. Using the dependency information, it then produces GraphML elements.

I open the XML file in yEd, and use one of the layout engines in yEd and, there you have it - an ER diagram with edges indicating the foreign key constraints.

92 LOC to solve a decade-old problem. Not bad at all...

Here's the code:

import groovy.sql.*

def tables = [:]

def visitTable = { dbmd, schema, tableName ->
if (!tables[tableName]) {
tables[tableName] = new HashSet()
}
def keyRS = dbmd.getExportedKeys(null, schema, tableName)
while (keyRS.next()) {
tables[tableName] << keyRS.getString("FKTABLE_NAME")
}
keyRS.close()
}

def config = [
host: "localhost", port: 3306,
dbname: "mydb", username: "myname", password: "mypass",
driver: "com.mysql.jdbc.Driver",
schema: "myschema" ]
def url = "jdbc:mysql://${config.host}/${config.dbname}"

def sql = Sql.newInstance(url, config.username, config.password, config.driver)
def dbmd = sql.connection.metaData

def tableRS = dbmd.getTables(null, config.schema, null, "TABLE")
while (tableRS.next()) {
visitTable(dbmd, config.schema, tableRS.getString("TABLE_NAME"))
System.err.print "."
}
System.err.println ""
tableRS.close()

sql.connection.close()

println """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns/graphml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:y="http://www.yworks.com/xml/graphml"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns/graphml
http://www.yworks.com/xml/schema/graphml/1.0/ygraphml.xsd">
<key for="node" id="d0" yfiles.type="nodegraphics"/>
<key attr.name="description" attr.type="string" for="node" id="d1"/>
<key for="edge" id="d2" yfiles.type="edgegraphics"/>
<key attr.name="description" attr.type="string" for="edge" id="d3"/>
<key for="graphml" id="d4" yfiles.type="resources"/>
<graph id="${config.schema}" edgedefault="directed">"""

tables.each { k,v ->
nodeId = "${config.schema}_${k}"
println """<node id="${nodeId}">
<data key="d0">
<y:ShapeNode>
<y:Geometry height="30.0" width="${nodeId.length() * 8}.0" x="0.0" y="0.0"/>
<y:Fill color="#CCFFFF" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content"
fontFamily="Dialog" fontSize="13" fontStyle="plain"
hasBackgroundColor="false" hasLineColor="false"
height="19.92626953125" modelName="internal" modelPosition="c"
textColor="#000000" visible="true" width="37.0"
x="5.5" y="5.036865234375">${k}</y:NodeLabel>
<y:Shape type="rectangle"/>
<y:DropShadow color="#B3A691" offsetX="2" offsetY="2"/>
</y:ShapeNode>
</data>
</node>"""
}

tables.each { k,v ->
v.each { referer ->
edgeId = "${config.schema}_${referer}_${k}"
println """<edge id="${edgeId}" source="${config.schema}_${referer}" target="${config.schema}_${k}">
<data key="d2">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="13.5" tx="0.0" ty="-15.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" distance="2.0" fontFamily="Dialog"
fontSize="12" fontStyle="plain" hasBackgroundColor="false"
hasLineColor="false" height="4.0" modelName="six_pos"
modelPosition="tail" preferredPlacement="anywhere" ratio="0.5"
textColor="#000000" visible="true" width="4.0"
x="2.0000069969042897" y="18.5"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>"""
}
}

println """<data key="d4">
<y:Resources/>
</data>
</graph>
</graphml>"""



Wednesday, May 23, 2007

List of question marks

Using only what a programming language standard API can provide, how do you generate a comma-separated list of question marks to be used as placeholders in a typical JDBC prepared statement? You know, the kind of "select * from tbl where code in (?, ?, ?, ?, ?)".

I tried to do it with the languages that I know. Say I want n question marks...

Java:
StringBuffer buf = new StringBuffer("?");
for (int i = 2; i <= n; i++) {
buf.append(", ?");
}
result = buf.toString();

Groovy:
def s = ('?' * n).toList().join(', ');

Ruby:
s = ('?' * n).split(//).join(', ')