|
演算子は左結合であるため、そのテーブルの行は次のように解析されます。
('Key' | 'Value') | 'Comments'
次に、各行の開始位置と終了位置を検出するためにできることは、|
operator にそのオペランドを含むリストを返させ、次に|
左側のオペランド (つまりthis
) がリストかどうかをそれぞれに尋ねることです。そうであれば、それは行の継続であることを意味します。リストでない場合は、新しい行であることを意味します。
Object メタクラスでのオーバーライドを避けるために、 Categoryを使用してこれらのデータセットを解析する DSL の完全な例を次に示します。
@Category(Object)
class DatasetCategory {
// A static property for holding the results of the DSL.
static results
def or(other) {
if (this instanceof List) {
// Already in a row. Add the value to the row.
return this << other
} else {
// A new row.
def row = [this, other]
results << row
return row
}
}
}
// This is the method that receives a closure with the DSL and returns the
// parsed result.
def dataset(Closure cl) {
// Initialize results and execute closure using the DatasetCategory.
DatasetCategory.results = []
use (DatasetCategory) { cl() }
// Convert the 2D results array into a list of objects:
def table = DatasetCategory.results
def header = table.head()
def rows = table.tail()
rows.collect { row ->
[header, row].transpose().collectEntries { it }
}
}
// Example usage.
def data = dataset {
'Key' | 'Value' | 'Comments'
1 | 'foo' | 'something'
2 | 'bar' | 'something else'
}
// Correcness test :)
assert data == [
[Key: 1, Value: 'foo', Comments: 'something'],
[Key: 2, Value: 'bar', Comments: 'something else']
]
この例では、テーブルをマップのリストとして解析しましたが、DSL クロージャーが実行された後は、DatasetCategory の結果で必要なことを行うことができるはずです。