それらを使って非常に簡単なDSLを定義してみたいと思います。
ちなみにこちらの記事が良く纏まっていて参考にさせていただきました。
まずは定義したDSLは以下の様になります。
hello { message { value "hoge" }}
なんとなく分るとは思いますがこのように定義すると「Hello,hoge」と出るようなものを定義しました。
普通こんな「ドメイン」無いとは思いますが^^;
まずはDSLを定義したファイルを読み込んで実行クラスを示します。
class Main { static main(args){ run( new File("src/main/resources/dsl.groovy")) } static run(File file){ Script script = new GroovyShell().parse(file.text) Message mes = new Message() script.metaClass = createEMC(script.class,{ ExpandoMetaClass emc -> emc.hello = { Closure cl -> cl.delegate = new HelloDelegate(mes) cl.resolveStrategy = Closure.DELEGATE_FIRST cl() } }) script.run() printMessage(mes) } static ExpandoMetaClass createEMC(Class clazz, Closure cl){ ExpandoMetaClass emc = new ExpandoMetaClass(clazz,false) cl(emc) emc.initialize() emc } static printMessage(Message message){ println "${message.hello}${message.mes}" }}
上記ソースはExpandoMetaClassを使用してScriptクラスの振る舞いを拡張し、その振る舞い自体は、
Closure#delegateに別途定義したHelloDelegateを渡しています。
delegateはClosureのthisのようなものでこちらの記事に詳しく解説されています。
#こうした先人達の記事は非常に助かり、私も大いに助けられています。
これらを使用することによってDSLの定義が可能になります。
ちなみにサンプルソースはこちらにアップしています。良かったら参考にしてみてください。
GitHubの実験代わりのものなのでブランチの切り方がおかしいですが、気にしないでください。