Quick and Easy Object Persistence: pBeans + Groovy Beans

id:n-tさんのとこより。

最初はタイトルのGroovyの単語にひかれて記事読んだのだけど実はpBeansがおもしろそう。
こっちはpBeansのサイト

pBeans is a Java based persistence framework and an Object/Relational (O/R) database mapping layer. It is designed to be simple to use and completely automated.

O/Rマッピングってよく知らないのだけどあらかじめTableの定義を自分でしなくてもいいものなの?スキーマつくっといてサンプル動かしたらいくつかTableが勝手に作られた。おもしろいなー。JavaDocをちらと見る限りそれほどクラス数が多くないのでソース読んでみたい。

File#eachFileRecurse(groovy.lang.Closure closure)を使ってみる

Groovy JDKの一覧ってちょっと前に比べても随分増えたような…。ところでなんでJavaDocみたいな書き方じゃないのかな。どれがどのメソッドの説明かわかりにくいよ。

2週間ほど前に書いた例題3を書き直してみる。これは便利。

import java.io.*

// directory構造を読む 引数がfileではだめ
new File(args[0]).eachFileRecurse { file |
    if (file.isFile()) {
        file.withReader { reader |
            // 読めたら3文字出力
            if ( (line = reader.readLine() ) != null) {
                i = 0
                line.each {if (i++ < 3) print it}
                print "\n" 
            }
        }
    }
}

あとは正規表現をうまく使えればきっと役に立つはず。

もうちょっとGroovy知ってS2GroovyBuilderが使いこなせるようになりたい。

sort()の使い方

これもGroovy: A Dynamic OO Language for the JVMのコードを少し変更してみて動かしてみる。
じつはよくわからなかったりする。

class Fruit {name ; weight }
list = [new Fruit(name:"orange", weight:100),
        new Fruit(name:"watermelon", weight:300),
        new Fruit(name:"apple", weight:100)]

// それぞれclone()して試してみる
clone = { list.clone() }

// これはsortする前
assert clone().name ==
        ["orange", "watermelon", "apple"]

// nameで昇順。納得できる。
assert clone().sort{ |fruit| fruit.name }.name ==
        ["apple", "orange", "watermelon"]

// この結果って正しい?
// 感覚的に["apple", "orange", "watermelon"]になるかと思ってた…
assert clone().sort{ [it.name, it.weight] }.name ==
        ["watermelon", "apple", "orange"]

// クロージャをパラメータで渡すとこうなるらし。
// <=>の意味がよくわからず。
assert clone().sort{ | a, b | a.name <=> b.name }.name ==
        ["apple", "orange", "watermelon"]

JavaからGroovyスクリプトを呼び出す(interfaceを使って)

Groovy: A Dynamic OO Language for the JVMにあるコードなのだけど、自分でもちょこっと変えて動かしてみる。ちゃんと動くものをのっけとけばあとでコピペできて便利ということで。Interfaceを使わない呼び出しもできるようだけど、使ったほうが少しコードが簡単になるみたい。
(注)えっと、S2OpenAMFのサンプル(Calculator)がわかりやすかったのでほぼそのまんまを使わせてもらいました。
気づいたことは一点

  • interfaceを使う場合は実装する側(Groovyのスクリプト)はメソッドのシグネチャをちゃんとinterfaceにあわせなければいけない(省略してはいけない。)。
// Javaのinterface
package test;

public interface Calculator {
    
    int plus(int a, int b);

}
// Javaのinterfaceを実装したgroovyスクリプト
import test.*

class CalculatorImpl implements Calculator {
    
 /*次のように戻り値の型や引数の型を省略すると実行時に
 呼び出し側でAbstractMethodErrorが発生するので注意。
    plus(a, b) {
        a + b
    }
 */    
     
    int plus(int a, int b) {
        a + b
    }
}
// groovyスクリプトを呼び出すJavaプログラム
package test;
import java.io.*;
import groovy.lang.*;

public class Client {
    
    public static void main(String args[])  {
        try {
            ClassLoader parent = 
                Thread.currentThread().getContextClassLoader(); 
            
            GroovyClassLoader loader = 
                new GroovyClassLoader( parent ); 
            
            Class groovyClass = 
                loader.parseClass( new File(args[0])); 
            
            Calculator calc = (Calculator) groovyClass.newInstance(); 
            
            int answer = calc.plus(Integer.parseInt(args[1]), 
                                    Integer.parseInt(args[2])); 
            
            System.out.println(answer);
        
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

classpathを通してコンパイル&実行 
実行するにはgroovy-1.0-beta-5.jar、asm-util-1.4.1.jar、asm-1.4.1.jarの3つを使用

C:\work\groovy\java>javac -classpath C:\groovy\groovy-1.0-beta-5.jar test\*.java

C:\work\groovy\java>java -classpath .;C:\groovy\groovy-1.0-beta-5.jar;C:\groovy\lib\asm-util-1.4.1.jar;C:\groovy\lib\asm-1.4.1.jar test.Client CalculatorImpl.groovy 5 10
15

groovyスクリプト名と5と10の3つを引数で渡す。5+10の結果の15が表示される。

AntのScriptタスクとant-contribのタスクで条件分岐やループを試してみた

ちょっとつかってみて感想など

  • Scriptにgroovyを使った場合:
    • scriptからantのpropertyにアクセスできることは確認できた
    • scriptからのtargetの実行のさせかたわからない(そもそも可能なのか?)
    • scriptの中で「this」にアクセスできない。
  • ant-contribを使った場合:参考:おいぬま日報(不定期)
    • ForやForeachタスクの中でAntCallタスク使えない
    • Ifタスクはelseifやelseを使うととても可読性が落ちる

柔軟性が高いのはやっぱりGroovyのAntBuilderかなー、と思った。AntBuilderでant-contribのタスク使うことも出来るのかな?しかし、Antのタスクってけっこうたくさんある。

情報をくださったid:udagawaさんid:dannさんありがとうございました。お二人はGroovyのAntBuidlerについてはどんなふうに考えているのかなーと気になったりします。