よく使いそうなGroovy使い方メモ

Groovy のスクリプトを書いてて、よく利用しそうな実装方法を随時メモしていく。

#演算子
##エルビス演算子で変数を初期化する

__参考__

- [Groovy学習５　使用できる演算子まとめ - Symfoware](http://symfoware.blog68.fc2.com/blog-entry-1172.html)

```groovy:
a = 'A'    ?: 'a'
b = [1, 2] ?: 'b'
c = -1     ?: 'c'
d = true   ?: 'd'

println "a=${a}, b=${b}, c=${c}, d=${d}"

w = ''    ?: 'w'
x = []    ?: 'x'
y = 0     ?: 'y'
z = false ?: 'z'

println "w=${w}, x=${x}, y=${y}, z=${z}"
```

```text:実行結果
a=A, b=[1, 2], c=-1, d=true
w=w, x=x, y=y, z=z
```

`<値A> ?: <値B>` で、 `<値A>` が真と評価される値の場合はそれ自身が、偽と判断される場合は `<値B>` が評価される。

#with を使ってオブジェクトのプロパティを初期化する
```groovy:
def hoge = new Hoge()

hoge.with {
    id = 10
    name = 'hoge'
}

println "id=${hoge.id}, name=${hoge.name}"

def class Hoge {
    def name
    def id
}
```

```text:実行結果
id=10, name=hoge
```

- `with()` メソッドにクロージャを渡すと、その中で `with()` メソッドを呼び出したオブジェクトのフィールドに直接アクセスできる。
- あくまでクロージャーなので、メソッドの実行やロジックの記述も可能。

#プロパティ・メソッド一覧を取得する
```groovy:
import java.nio.file.Paths
def obj = Paths.get('hoge.txt')

println '[properties]'
obj.properties.each { property ->
    println property
}

println()
println '[methods]'
obj.metaClass.methods.each { method ->
    println method
}
```

```text:実行結果
[properties]
class=class sun.nio.fs.WindowsPath
absolute=false
pathForPermissionCheck=hoge.txt
fileSystem=sun.nio.fs.WindowsFileSystem@6f9e305d
nameCount=1
unc=false
fileName=hoge.txt
pathForExceptionMessage=hoge.txt
root=null
absolutePath=D:\tmp\groovy\hoge.txt
empty=false
pathForWin32Calls=D:\tmp\groovy\hoge.txt
parent=null

[methods]
public boolean java.lang.Object.equals(java.lang.Object)
public final native java.lang.Class java.lang.Object.getClass()
public native int java.lang.Object.hashCode()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
public java.lang.String java.lang.Object.toString()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final boolean sun.nio.fs.AbstractPath.endsWith(java.lang.String)
public final java.util.Iterator sun.nio.fs.AbstractPath.iterator()
（以下略）
```

`properties` でプロパティ一覧を、 `metaClass.methods` でメソッド一覧を取得できる。

#コマンドライン引数を取得する

__参考__

- [HongoLog: Groovy : Command line arguments -- Groovyでコマンドライン引数](http://hongolog.blogspot.jp/2011/01/groovy-command-line-arguments-groovy.html)

```groovy:test.groovy
println "args.class = ${args.class}"
println "args = ${args}"
```

```text:実行
>groovy test.groovy hoge fuga
args.class = class [Ljava.lang.String;
args = [hoge, fuga]
```

`args` という String の配列変数から取得できる。

#コマンドの実行

__参考__

- [Groovy からプログラムを実行するには？：experiment：So-net blog](http://experiment.blog.so-net.ne.jp/2010-01-14)

##基本
```groovy:
'notepad'.execute()
```

String クラスの `execute()` メソッドを使うと、コマンドが実行できる。
コマンドは非同期で実行されるので、コマンドを実行したら終了を待つこと無く次のステップに進む。

###コマンドの終了を待機する
```groovy:
'notepad'.execute().waitFor()
println 'done'
```

`Process` クラスの `waitFor()` メソッドでコマンドの終了を待機できる。

上記実装の場合、メモ帳が閉じられたら `println 'done'` が実行される。

##コマンドのリターンコードを取得する
```groovy:
exitValue = 'notepad'.execute().waitFor()
println "exitValue=${exitValue}"
```

```text:実行結果
exitValue=0
```

`waitFor()` メソッドの戻り値が、コマンドのリターンコードになっている。

[waitFor() | Process (Java Platform SE 6)](http://docs.oracle.com/javase/jp/6/api/java/lang/Process.html#waitFor%28%29)

##コマンドプロンプトのコマンドを実行する
```groovy:
'cmd /c dir'.execute()
```

`cmd /c <コマンド>` で実行できる。

##実行したコマンドが標準出力に出力した結果を取得する
```groovy:
println 'cmd /c echo /?'.execute().text
```

```text:実行結果
メッセージを表示したり、コマンド エコーの ON と OFF を切り替えます。

  ECHO [ON | OFF]
  ECHO [メッセージ]

現在のエコー設定を表示するには、パラメーターを指定せずに ECHO と入力して
ください。
```

[getText()](http://groovy.codehaus.org/groovy-jdk/java/lang/Process.html#getText%28%29) というメソッドがあり、コマンドが出力した結果を String でまとめて取得できる。

[Process (Groovy JDK)](http://groovy.codehaus.org/groovy-jdk/java/lang/Process.html)

#コマンドライン引数を解析する

__参考__

- [CliBuilder (groovy 2.2.1 API)](http://groovy.codehaus.org/gapi/groovy/util/CliBuilder.html#parse%28def%29)
- [プログラミングGROOVY](http://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0GROOVY-%E9%96%A2%E8%B0%B7-%E5%92%8C%E6%84%9B/dp/4774147273)

Groovy には Apache Commons CLI を簡単に利用するための CliBuilder というクラスが標準で組み込まれていて、これを使えば簡単にコマンドライン引数の解析ができる。

##基本
```groovy:
def cli = new CliBuilder(usage: 'hoge')

cli.with {
    a 'A option'
}

def arguments = ['-a']

def options = cli.parse(arguments)

if (options.a) {
    println('a オプションが指定されました')
}
```

```text:実行結果
a オプションが指定されました
```

基本は次の順序で使用する。

1. `CliBuilder` のインスタンスを生成する。
1. オプションを定義する。
1. コマンドライン引数を解析する。
1. 解析結果を参照する。

###解析でエラーと判定された場合の動作
```groovy:
def cli = new CliBuilder(usage: 'hoge')

cli.with {
    a required: true, 'A option'
}

def arguments = ['-b']

def options = cli.parse(arguments)

println "options = ${options}"
```

```text:実行結果
error: Missing required option: a
usage: hoge
 -a   A option
options = null
```

`parse()` メソッドでコマンドライン引数を解析した結果、エラーと判定された場合、エラー内容と usage が表示される（上記例の場合、必須指定の `-a` オプションが指定されていない）。

例外はスローされず、 `parse()` メソッドの戻り値が null になる。

##usage を表示する
```groovy:
def cli = new CliBuilder(usage: 'hoge')

cli.with {
    a 'A option'
}

cli.usage()
```

```text:実行結果
usage: hoge
 -a   A option
```

`usage()` メソッドを実行すると、 usage が表示される。

##オプションを必須入力にする
```groovy:
cli.with {
    a required: true, '必須オプション'
}
```

`required` に `true` を指定すると、そのオプションは必須入力になる。

##オプションに長い名前の別名を定義する
```groovy:
def cli = new CliBuilder(usage: 'hoge')

cli.with {
    a longOpt: 'aaa', 'A option'
}

def arguments = ['--aaa']

def options = cli.parse(arguments)

if (options.a) {
    println 'a オプションが指定されました。'
}

cli.usage()
```

```text:実行結果
a オプションが指定されました。
usage: hoge
 -a,--aaa   A option
```

`longOpt` でオプションの別名を定義できる。

##オプションにパラメータを定義する
```groovy:
def cli = new CliBuilder(usage: 'hoge')

cli.with {
    a args: 1, 'A option'
}

def arguments = ['-a', 'a option value']

def options = cli.parse(arguments)

if (options.a) {
    println "a オプション に ${options.a} が渡されました。"
}

cli.usage()
```

```text:実行結果
a オプション に a option value が渡されました。
usage: hoge
 -a <arg>   A option
```

`args` に `1` を指定すると、オプションに必須パラメータを定義できる。

###usage で表示するオプションの名前を変更する
```groovy:
def cli = new CliBuilder(usage: 'hoge')

cli.with {
    a args: 1, argName: 'a parameter', 'A option'
}

cli.usage()
```

```text:実行結果
usage: hoge
 -a <a parameter>   A option
```

`argName` で usage に表示するオプションパラメータの名前を指定できる。

###オプションのパラメータを任意指定にする
```groovy:
def cli = new CliBuilder(usage: 'hoge')

cli.with {
    a args: 1, optionalArg: true, 'A option'
}

def arguments = ['-a']

def options = cli.parse(arguments)

if (options.a) {
    println "options.a = ${options.a}"
}
```

```text:実行結果
options.a = true
```

`optionalArg` に `true` を指定すると、オプションのパラメータ指定が任意になる。

###オプションパラメータを key=value 形式にする
```groovy:
def cli = new CliBuilder(usage: 'hoge')

cli.with {
    a args: 2, valueSeparator: '=', 'A option'
}

def arguments = ['-a', 'hoge=HOGE']

def options = cli.parse(arguments)

if (options.a) {
    println "options.a  = ${options.a}"
    println "options.as = ${options.as}"
}
```

```text:実行結果
options.a  = hoge
options.as = [hoge, HOGE]
```

`valueSeparator` を指定すると、オプションのパラメータを `key=value` のような形式で指定できる。
このとき、 `args` には `2` を指定しなければならない。

オプション名だけでパラメータの値を取得すると、 `valueSeparator` で指定した文字の右側の値だけが取得できる。

オプション名の末尾に `s` を付けて値を取得すると、 List が返される。
List には、 `valueSeparator` でパラメータを split した結果が設定されている。

つまり、次のような使い方もできる。

```groovy:
def cli = new CliBuilder(usage: 'hoge')

cli.with {
    a args: 3, valueSeparator: ',', 'A option'
}

def arguments = ['-a', 'hoge,fuga,piyo']

def options = cli.parse(arguments)

if (options.a) {
    println "options.as = ${options.as}"
}
```

```text:実行結果
options.as = [hoge, fuga, piyo]
```

ただし、パラメータの途中にスペースがあるとうまく解析できないので注意。
例えば、 `-a hoge, fuga, piyo` としてしまうと、 `-a` のオプションは `hoge,` だけになってしまう。

##長い名前だけでオプションを定義する
```groovy:
def cli = new CliBuilder(usage: 'hoge')

cli.with {
    _ longOpt: 'aaa', 'A option'
    _ longOpt: 'bbb', 'B option'
}

cli.usage()
```

```text:実行結果
usage: hoge
    --aaa   A option
    --bbb   B option
```

`_` という名前でオプションを定義して、 `longOpt` を指定すれば、長い名前だけでオプションを定義できる。


##引数を取得する
```groovy:
def cli = new CliBuilder()
cli.with {
    a 'a option'
}

def cmd = cli.parse(['-a', 'hoge', 'fuga', 'piyo'])

println cmd.arguments()
```

```text:
[hoge, fuga, piyo]
```

- `arguments()` メソッドでオプション以外の引数を list で取得できる。

#クラス単位でファイルを分割する
```text:フォルダ構成
|-Main.groovy
|-Hoge.groovy
`-sub/
   `-Fuga.groovy
```

```groovy:Hoge.groovy
def class Hoge {
    def method() {
        println 'hoge'
    }
}
```

```groovy:Fuga.groovy
package sub

def class Fuga {
    def method() {
        println 'fuga'
    }
}
```

```groovy:Main.groovy
def hoge = new Hoge()

hoge.method()
```

```text:実行
> groovy Main
hoge
```

- ファイル名と同じ名前のクラスを定義する。
- パッケージは、クラスパスでしていしたディレクトリを起点として定義する（デフォルトは、実行ディレクトリにクラスパスが通る）。


#ファイル（フォルダ）検索
##指定したフォルダ直下のみ対象
```groovy:
// 全フォルダ・全ファイル
new File('path/to/dir').eachFile { println it.name }

// ファイルのみ
import groovy.io.FileType
new File('path/to/dir').eachFile(FileType.FILES) { println it.name }

// フォルダのみ
new File('path/to/dir').eachDir { println it.name }

// 名前が指定した正規表現に一致するファイルのみ
import groovy.io.FileType
new File('path/to/dir').eachFileMatch(FileType.FILES, ~/[a-z]+.txt/) { println it.name }

// 名前が指定した正規表現に一致するフォルダのみ
new File('path/to/dir').eachDirMatch(~/[a-z]+/) { println it.name }
```

##指定したフォルダ以下再帰的に検索
```groovy:
// 全フォルダ・全ファイル
new File('path/to/dir').eachFileRecurse { println it.name }

// ファイルのみ
import groovy.io.FileType
new File('path/to/dir').eachFileRecurse(FileType.FILES) { println it.name }

// フォルダのみ
import groovy.io.FileType
new File('path/to/dir').eachFileRecurse(FileType.DIRECTORIES) { println it.name }
```

__参考__

- [ディレクトリを再帰的に辿っていってファイル探すメモ - 地下アイドルの手記](http://d.hatena.ne.jp/ug_idol/20081211/1229006764)

#ファイル読み込み
##全行読み込み
```groovy:
def text = new File('hoge.txt').text

// 文字コード指定
def text = new File('hoge.txt').getText('Shift_JIS')
```

##１行づつ読み込み
```groovy:
new File('hoge.txt').eachLine { println it }

// 文字コード指定
new File('hoge.txt').eachLine('UTF-8') { println it }
```

#ファイル書き込み
##追記
```groovy:
// append()メソッド
new File('hoge.txt').append('追記')

// append()メソッド：文字コード指定
new File('hoge.txt').append('ほげ', 'Shift_JIS')

// <<演算子
new File('hoge.txt') << 'append text'
```

##上書き
```groovy:
// write()メソッド
new File('hoge.txt').write('上書き')

// write()メソッド：文字コード指定
new File('hoge.txt').write('ぴよ', 'Shift_JIS')

// textプロパティ
new File('hoge.txt').text = 'append'

// setText()メソッド：文字コード指定
new File('hoge.txt').setText('ふが', 'Shift_JIS')
```

##BufferedWriter の取得
```groovy:
def writer = new File('hoge.txt').newWriter()
```

この場合は __上書き__ モードで取得される。
`newWriter()` の引数に `true` を渡せば __追記モード__ になる。

```groovy:文字コード指定
def writer = new File('hoge.txt').newWriter('UTF-8')

// 追記モード
def writer = new File('hoge.txt').newWriter('UTF-8', true)
```

##withWriter() でクローズ処理を省略
```groovy:
// デフォルト文字コードで上書き
new File('hoge.txt').withWriter { writer ->
    writer << 'aaa'
}

// 文字コードを指定して上書き
new File('hoge.txt').withWriter('UTF-8') { writer ->
    writer << 'bbb'
}

// デフォルト文字コードで追記
new File('hoge.txt').withWriterAppend { writer ->
    writer << 'ccc'
}

// 文字コードを指定して追記
new File('hoge.txt').withWriterAppend('Shift_JIS') { writer ->
    writer << 'ddd'
}
```

#正規表現
##マッチした部分文字列だけを抽出する
```groovy:
def str = ('hoge 123 fuga' =~ /[0-9]+/)[0]
println "str = ${str}"
```

```text:実行結果
str = 123
```

#データベース操作
__参考__

- [プログラミングGROOVY](http://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0GROOVY-%E9%96%A2%E8%B0%B7-%E5%92%8C%E6%84%9B/dp/4774147273)

##接続
```groovy:
import groovy.sql.Sql

def url    = 'jdbc:mysql://localhost/test'
def user   = 'test'
def pass   = 'test'
def driver = 'com.mysql.jdbc.Driver'

def sql = Sql.newInstance(url, user, pass, driver)
```

###各 RDBMS の URL とドライバ名
|データベース製品|URL                                         |ドライバ（クラス名）             |
|:---------------|:-------------------------------------------|:--------------------------------|
|Oracle          |`jdbc:oracle:thin:@<host>:<port>:<database>`|`oracle.jdbc.driver.OracleDriver`|
|MySQL           |`jdbc:mysql://<host>:<port>/<database>`     |`com.mysql.jdbc.Driver`          |
|PostgreSQL      |`jdbc:postgresql://<host>:<port>/<database>`|`org.postgresql.Driver`          |
|HSQLDB          |`jdbc:hsqldb:hsql://<host>:<port>`          |`org.hsqldb.jdbc.JDBCDriver`     |

__参考__

- [（補足）Oracleへの接続 | TECHSCORE(テックスコア)](http://www.techscore.com/tech/Java/JavaEE/JDBC/oracle-1/)
- [MySQL ::   MySQL 5.1 リファレンスマニュアル :: 24.4.5.1 JDBC の基本コンセプト](http://dev.mysql.com/doc/refman/5.1/ja/connector-j-usagenotes-basic.html)
- [jdbc経由でPostgreSQLにアクセスする - いろいろ書いてみる - Yahoo!ブログ](http://blogs.yahoo.co.jp/kensinisnek/11027082.html)
- [[ThinkIT] 第7回：データベースの利用 (1/3)](http://thinkit.co.jp/free/tech/3/7/1.html)

##検索
###複数行取得
```groovy:eachRow()メソッド
sql.eachRow('SELECT * FROM TEST_TABLE') { println it }

// カラム名を指定して値を取得
sql.eachRow('SELECT * FROM TEST_TABLE') {
    println "ID=${it.id}, CODE=${it.code}, VALUE=${it.value}"
}

// インデックスを指定して値を取得
sql.eachRow('SELECT * FROM TEST_TABLE') {
    println "ID=${it[0]}, CODE=${it[1]}, VALUE=${it[2]}"
}
```

```groovy:query()メソッド
sql.query('SELECT * FROM TEST_TABLE') { rs ->
    while (rs.next()) {
        println "ID=${rs.getInt('ID')}, CODE=${rs.getString('CODE')}, VALUE=${rs.getString('VALUE')}"
    }
}
```

`query()` メソッドを使うと、クロージャに [ResultSet](http://docs.oracle.com/javase/jp/7/api/java/sql/ResultSet.html) が渡される。

```groovy:rows()メソッド
def list = sql.rows('SELECT * FROM TEST_TABLE')

list.each { println it }
```

`rows()` メソッドは、結果をすべて読み込んでその結果を返す。

###単一行取得
```groovy:firstRow()メソッド
def result = sql.firstRow 'SELECT COUNT(*) FROM TEST_TABLE'
println result.'COUNT(*)'
```

##更新
```groovy:
def id     = 10
def code   = 'hoge'
def value  = 'HOGE'

sql.execute """
    INSERT INTO TEST_TABLE (
        ID
       ,CODE
       ,VALUE
    ) VALUES (
        ${id}
       ,${code}
       ,${value}
    )
"""
```

`GString` を使えば、勝手に PreparedStatement を使ってくれる。

##トランザクション
```groovy:
sql.withTransaction {
    sql.execute "DELETE FROM TEST_TABLE WHERE ID=4"
    throw new RuntimeException("test runtime exception")
}
```

`withTransaction` に渡したクロージャ内が１トランザクションで実行される。

クロージャ内で例外がスローされると、トランザクションがロールバックされる。
ただし、スローされる例外によって以下のように若干動作が異なる。

|スローされる例外                      |動作                            |
|:-------------------------------------|:-------------------------------|
|`RuntimeException` 及び `SQLException`|即座にロールバックされる        |
|`Exception`                           |ロールバックもコミットもされない|

`RuntimeException` 及び `SQLException` がスローされると、その時点でロールバックが実行される。

しかし、ただの `Exception` がスローされた場合はロールバックもコミットもされない。
そのままスクリプトが終了した場合、変更は DB に反映されない。

つまり、 `Exception` がスローされても、手動で `sql.connection.commit()` としてやれば変更をコミットできる（使いドコロは不明だけど）。


#MarkupBuilder で XML, HTML を生成する方法

__参考__

- [Groovy - Using MarkupBuilder for Agile XML creation](http://groovy.codehaus.org/Using+MarkupBuilder+for+Agile+XML+creation)
- [MarkupBuilder (Groovy 2.2.1)](http://groovy.codehaus.org/api/groovy/xml/MarkupBuilder.html)

##基本
```groovy:
import groovy.xml.MarkupBuilder

def writer = new StringWriter()

new MarkupBuilder(writer).div {
    b('MarkupBuilder!!')
}

println writer
```

```html:実行結果
<div>
  <b>MarkupBuilder!!</b>
</div>
```

- `MarkupBuilder` を new して、あとはタグでマークアップしているかのように構造を記述する。
- `MarkupBuilder` のインスタンスを単純に `toString()` すると、末尾によくわからないタグ名がくっついてくるので、 `StringWriter` を使ってテキスト表現を取得する。

```html:単純にMarkupBuilderのtoString()を実行した場合
<div>
  <b>MarkupBuilder!!</b>
</div>div
```

なんか、最後に `div` という文字列がくっついてくる。

##属性を指定する
```groovy:
// 基本
new MarkupBuilder().input(id: 'hoge')

/* 出力結果
<input id='hoge' />
*/

// 予約語とかぶる場合は文字列で指定する
new MarkupBuilder().input('class': 'fuga')

/* 出力結果
<input class='fuga' />
*/
```

##子タグを指定する
```groovy:
new MarkupBuilder(writer).div {
    input(id: 'hoge')
}

/* 出力結果
<div>
  <input id='hoge' />
</div>
*/
```

##内容を指定する
```groovy:
// 内容だけ
new MarkupBuilder().div('content')

/* 出力結果
<div>content</div>
*/

// 属性も指定する
new MarkupBuilder().div('class': 'fuga', 'content', id: 'hoge')

/* 出力結果
<div class='fuga' id='hoge'>content</div>
*/

// 子タグと一緒に指定する
new MarkupBuilder().div('content') {
    p('paragraph')
}

/* 出力結果
<div>content
  <p>paragraph</p>
</div>
*/
```

単独文字列の引数をタグ宣言に渡すと、それがタグの内容になる。

##属性をダブルクォーテーションで括る
デフォルトだと、属性の値はシングルクォーテーションで括られる。
ダブルクォーテーションで括るようにするには、 `setDoubleQuotes(boolean)` メソッドで `true` を設定する。

```groovy:
def builder = new MarkupBuilder()

builder.setDoubleQuotes(true)

builder.input(id: 'hoge') // => <input id="hoge" />
```

##ロジックを書いて動的に構造を定義する
```groovy:
bool = true

new MarkupBuilder().div {
    if (bool) {
        p('true!!')
    } else {
        p('false!!')
    }
}
```

```html:結果
<div>
  <p>true!!</p>
</div>
```

- クロージャなので、ロジックを書くことができる。

#ConfigSlurper で設定ファイルを作成する

__参考__

- [GroovyのConfigSlurperがめっちゃ便利 - No Programming, No Life](http://npnl.hatenablog.jp/entry/20101121/1290356773)

##設定ファイルのロード
```groovy:config.groovy
hoge {
    aaa = 'AAA'
    fuga {
        bbb = 'BBB'
        ccc = 'CCC'
    }
}
```

```groovy:
def config = new ConfigSlurper().parse(new File('config.groovy').toURL())

println config
```

```text:実行結果
[hoge:[aaa:AAA, fuga:[bbb:BBB, ccc:CCC]]]
```

- groovy のクロージャーを使って階層構造で宣言したファイルを設定ファイルとして読み込むことができる。

##出力
```grppvy:
def config = new ConfigObject()

config.test = [1, 2, 3]

new File('out.groovy').withWriter { writer ->
    config.writeTo(writer)
}
```

#別の groovy スクリプトファイルを実行する

__参考__

- [プログラマメモ2: groovyで別groovyファイルをインクルードもどき。](http://programamemo2.blogspot.jp/2007/10/groovygroovy.html)

```text:フォルダ構成
|- main.groovy
`- sub.groovy
```

```groovy:main.groovy
evaluate(new File('./sub.groovy'))

println 'main.groovy'
println sub
```

```groovy:sub.groovy
println 'sub.groovy'

sub = 'SUB'
```

```text:実行結果
sub.groovy
main.groovy
SUB
```

- `evaluate()` で指定した groovy ファイルを実行できる。
- 実行した groovy ファイルの中で定義した変数を参照できる。
- 簡易的な設定ファイルとして便利そう


#コマンドラインでパスワードの入力を求める
```groovy:
Console console = System.console()
char[] chars = console.readPassword('please type password > ')
String pass = new String(chars)
println pass
```

#java コマンドで実行する

Groovy はインストールされていないけど Java はインストールされている環境で Groovy のスクリプトを動かしたくなったとき用。

最低でも以下の jar ファイルが必要。

- `%GROOVY_HOME%/embeddable/groovy-all-x.x.x.jar`

他に依存する jar がなければ以下のコマンドで実行できる。

```text:
>java -jar groovy-all-x.x.x.jar script.groovy
```

他に依存する jar が存在する場合は、以下のコマンドで実行する。

```text:
>java -cp groovy-all-x.x.x.jar;<依存する jar のパス...> groovy.ui.GroovyMain script.groovy
```

※-jar オプションで jar ファイルを実行する場合、クラスパスをコマンドラインから指定できない仕様になっているため。

commons の CLI を利用している場合は依存する jar として別途クラスパスを指定しなければいけないので注意。

__参考__

- [[Groovy] JavaコマンドでGroovyスクリプトを実行する | ルクサエンジニアのブログ](http://blog.luxa.jp/archives/627)


#ヒアドキュメント
##基本

```groovy:
println """hoge
fuga
piyo
"""
```

```text:出力結果
hoge
fuga
piyo
```

- シングルクォーテーション３つ、またはダブルクォーテーション３つで括ることで、ヒアドキュメントが書ける。
- ダブルクォーテーションの方は GString 扱いなので、変数の展開が可能。

##先頭の改行を無視させる
```groovy:
println """\
hoge
fuga
piyo
"""
```

```text:出力結果
hoge
fuga
piyo
```

- ヒアドキュメントの先頭に `\` を入れることで、先頭の改行を無視できる。

##コードのインデントで生まれるスペースを無視させる
```groovy:
    println """\
            |hoge
            |fuga
            |piyo
            |""".stripMargin()
```

```text:出力結果
hoge
fuga
piyo
```

- `stripMargin()` メソッドを実行することで、パイプ `|` から左のスペースを無視させることができる。


__参考__

- [Groovyのヒアドキュメント - Starlight](http://d.hatena.ne.jp/Kazuhira/20130715/1373878511)

#スレッド処理を実行する
```groovy:
println 'main thread : ' + Thread.currentThread().name

Thread.start {
    println 'new thread : ' + Thread.currentThread().name
}
```

```text:実行結果
main thread : Thread-15
new thread : Thread-16
```

`Thread.start()` にクロージャを渡すと、渡したクロージャが新しいスレッドで実行される。


#よく参照しそうな Groovy JDK の Javadoc
- [Groovy JDK](http://groovy.codehaus.org/groovy-jdk/)
 - [java.lang.Object](http://groovy.codehaus.org/groovy-jdk/java/lang/Object.html)
 - [java.lang.String](http://groovy.codehaus.org/groovy-jdk/java/lang/String.html)
 - [java.util.Collection](http://groovy.codehaus.org/groovy-jdk/java/util/Collection.html)
 - [java.util.List](http://groovy.codehaus.org/groovy-jdk/java/util/List.html)
 - [java.util.Map](http://groovy.codehaus.org/groovy-jdk/java/util/Map.html)
 - [java.io.File](http://groovy.codehaus.org/groovy-jdk/java/io/File.html)

- [Groovy 2.2.1 : Javadoc](http://groovy.codehaus.org/api/overview-summary.html)
 - [groovy.sql.Sql](http://groovy.codehaus.org/api/groovy/sql/Sql.html)