4

我想要一个 spock 数据驱动规范格式的数据集描述:

'Key'   |    'Value'    |    'Comments'
1       |    'foo'      |    'something'
2       |    'bar'      |    'something else'

这必须转换为类似 2D 数组的东西(或任何可能实现的东西)。

任何想法如何实现这个数据描述?

ps 最大的问题是换行检测,剩下的可以通过orObject的重载来实现metaClass

4

1 回答 1

5

|运算符是左关联的,因此该表中的一行将被解析为:

('Key' | 'Value') | 'Comments'

然后,您可以检测每一行的开始和结束位置是让|操作符返回一个包含其操作数的列表,然后为每个|询问左侧操作数(即this)是否是一个列表。如果是,则表示它是一行的延续;如果它不是一个列表,则意味着它是一个新行。

这是一个 DSL 的完整示例,它使用Category来解析这些数据集,以避免覆盖 Object 元类上的内容:

@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 的结果执行任何操作。

于 2012-12-20T00:30:42.203 回答